Parameters 是否有方法指示批处理文件中的最后n个参数?
在下面的示例中,我想从父批处理文件调用子批处理文件,并将所有剩余参数传递给子批处理文件Parameters 是否有方法指示批处理文件中的最后n个参数?,parameters,shell,cmd,Parameters,Shell,Cmd,在下面的示例中,我想从父批处理文件调用子批处理文件,并将所有剩余参数传递给子批处理文件 C:\> parent.cmd child1 foo bar C:\> parent.cmd child2 baz zoop C:\> parent.cmd child3 a b c d e f g h i j k l m n o p q r s t u v w x y z 在parent.cmd中,我需要从参数列表中删除%1,并只将其余参数传递给子脚本 set CMD=%1 %CMD%
C:\> parent.cmd child1 foo bar
C:\> parent.cmd child2 baz zoop
C:\> parent.cmd child3 a b c d e f g h i j k l m n o p q r s t u v w x y z
在parent.cmd中,我需要从参数列表中删除%1,并只将其余参数传递给子脚本
set CMD=%1
%CMD% <WHAT DO I PUT HERE>
set CMD=%1
%CMD%
我已经调查过使用%*的SHIFT,但这不起作用。虽然SHIFT将位置参数下移1,%*仍指原始参数
有人有什么想法吗?我应该放弃并安装Linux吗?
%*
将始终扩展到所有原始参数,很遗憾。但您可以使用以下代码片段构建包含除第一个参数外的所有参数的变量:
rem throw the first parameter away
shift
set params=%1
:loop
shift
if [%1]==[] goto afterloop
set params=%params% %1
goto loop
:afterloop
我认为可以缩短时间,不过。。。我不常写这种东西:)
不过应该可以用。这里有一个使用“for”命令的单行方法
for /f "usebackq tokens=1*" %%i in (`echo %*`) DO @ set params=%%j
此命令将第一个参数分配给“i”,其余参数(用“*”表示)分配给“j”,然后使用“j”设置“params”变量。您实际上可以这样做:
%*
如果这是行中的唯一内容,则扩展为执行第一个参数,并将所有其他参数传递给它。:) 另一种方法(几乎与Alxander Bird的方法相同),不在子shell中执行ECHO:
FOR /F "usebackq tokens=1*" %%I IN ('%*') DO SET params=%%J
那么,行吗
%CMD% <WHAT DO I PUT HERE>
问题是,如果参数中包含带引号的Sting,且其内部带有空格,则cmd.exe将对其进行适当的解析,以便使用带编号的参数(%1),但for将忽略引号。在这种特定的情况下,如果第一个参数包含一个或多个空格,这是很可能的,因为第一个参数可以是,例如,“C:\Program Files\Internet Explorer\iexplore.exe”
因此,这里将是另一个答案。警告如果参数中有«*»s或«»s,则此方法会产生扩展通配符的副作用。如果存在通配符但没有相应的文件,则跳过参数(非通配符参数保持原样)。如果参数必须保持不变,请寻找另一种方法
线路
%CMD% <WHAT DO I PUT HERE>
当然,您可以将skip var设置为任意数量的参数
解释:
(
@rem Starting block here, because it's read once and executed as one
@rem otherwise cmd.exe reads file line by line, which is waaay slower.
SETLOCAL ENABLEDELAYEDEXPANSION
SET skip=1
@rem if value contains unquoted non-paired parenthesis, SET varname=value
@rem confuses cmd.exe. SET "a=value" works better even if value has quotes.
FOR %%I IN (%*) DO (
IF !skip! LEQ 0 (
SET "params=!params! %%I"
@rem newline after SET to lower amount of pitfalls when arguments
@rem have unpaired quotes
) ELSE (
SET /A skip-=1
)
)
(
@rem get variables out of SETLOCAL block
@rem as whole block in parenthesis is read and expanded before executing,
@rem SET after ENDLOCAL in same block will set var to what it was before
@rem ENDLOCAL. All other envvars will be reset to state before SETLOCAL.
ENDLOCAL
SET "params=%params%"
)
@rem doing this outside of parenthesis block to avoid
@rem cmd.exe confusion if params contain unquoted closing round bracket
%CMD% %params%
虽然“for”解决方案在很多情况下确实是优越的,但对于一些简单的事情,我通常只保存并转移其他参数,然后像往常一样使用
%*
(实际上相同的策略通常适用于$*
或$@
中的{,ba,da,k,*}sh
):
示例:
不管怎样,我看到这个问题得到了很长的回答,但我想我会放弃我的两分钱,因为这是我没有看到的东西,因为这是我需要的答案,当我在几年前偶然遇到它时。。。然后说:“哦……嗯。”:)我遇到这个问题时遇到了一个类似的问题,但我用不同的方法解决了它。 我没有使用循环(如@Joey的回答)重新创建输入行,而是从输入字符串中删除了第一个参数
set _input=%*
set params=!_input:%1 =!
call OTHER_BATCH_FILE.cmd %params%
当然,这是假设所有参数都不同。我改进了Moshe Goren的答案,因为它似乎对我不起作用:
set _input=%*
call set params=%%_input:%1 =%%
@echo %params%
一模一样?这个问题用不起作用的代码来回答。我在我的问题中添加了一些陈述来帮助澄清,看起来我从Johannes那里得到了一个可靠的答案。哦,顺便说一下,当所有Maen从其他批次调用批次时,都使用call。否则,调用的批处理文件在被调用的批处理退出后将不会进一步运行。(可能与此相关,也可能与此无关,只是一些最佳实践:-)Windows 10有官方的bash,任何Windows都有非正式的win-bash.sourceforge.net。或者使用Cygwin,您可以随意设置完整的GNU环境。如果在参数中有赋值,例如“a=b”,这种方法将失败。然后,您将得到两个单独的参数“a”和“b”,失去=。正如Tbee所说,如果剩余参数中有
=
,则这不起作用。似乎唯一真正解决这个问题的方法是编写一个程序来正确提取参数-cmd shell太草率了。在这种情况下,引用参数cmd
还将几个字符视为参数分隔符,例如
或,
。如果两个参数之间有两个或多个连续空格,如果要保留这些空格,则此操作将完全失败。他们被缩短到一个空间!我希望SHIFT命令也为%*移位:(SHIFT不影响%*所以这会将所有原始参数传递给%run_me%,包括%1和%2。正如公认的答案所说,“%*将始终扩展到所有原始参数,很遗憾。”当第一个参数包含空格(引号)时,这会失败,例如“第一个参数”second third
将参数设置为参数“second third
注意:如果在调用脚本时没有附加参数,则%1
将被传递。除了传递%1之外,这还会给将来带来很多陷阱
:: run_and_time_me.cmd - run a command with the arguments passed, while also piping
:: the output through a second passed-in executable
@echo off
set run_me=%1
set pipe_to_me=%2
shift
shift
:: or
:: set run_me=%1
:: shift
:: set pipe_to_me=%1
:: shift
%run_me% %* | %pipe_to_me%
set _input=%*
set params=!_input:%1 =!
call OTHER_BATCH_FILE.cmd %params%
set _input=%*
call set params=%%_input:%1 =%%
@echo %params%