我想找到一个Windows批处理对应Bash的$@,它持有传递到脚本的所有参数的列表。
还是要我费心去换班?
我想找到一个Windows批处理对应Bash的$@,它持有传递到脚本的所有参数的列表。
还是要我费心去换班?
当前回答
你可以使用命令,以获得参数列表。
帮助:For /? 帮助:Setlocal /?
这是我的方法=
@echo off
::For Run Use This = cmd /c ""Args.cmd" Hello USER Scientist etc"
setlocal EnableDelayedExpansion
set /a Count=0
for %%I IN (%*) DO (
Echo Arg_!Count! = %%I
set /a Count+=1
)
Echo Count Of Args = !Count!
Endlocal
不需要Shift命令。
其他回答
%*似乎包含传递给脚本的所有参数。
下面的代码模拟了一个数组('params')——接受脚本接收到的参数,并将它们存储在变量params_1 ..Params_n,其中n=params_0=数组元素的个数:
@echo off
rem Storing the program parameters into the array 'params':
rem Delayed expansion is left disabled in order not to interpret "!" in program parameters' values;
rem however, if a parameter is not quoted, special characters in it (like "^", "&", "|") get interpreted at program launch
set /a count=0
:repeat
set /a count+=1
set "params_%count%=%~1"
shift
if defined params_%count% (
goto :repeat
) else (
set /a count-=1
)
set /a params_0=count
rem Printing the program parameters stored in the array 'params':
rem After the variables params_1 .. params_n are set with the program parameters' values, delayed expansion can
rem be enabled and "!" are not interpreted in the variables params_1 .. params_n values
setlocal enabledelayedexpansion
for /l %%i in (1,1,!params_0!) do (
echo params_%%i: "!params_%%i!"
)
endlocal
pause
goto :eof
% 1…%n和%*保存参数,但是访问它们可能很棘手,因为内容将被解释。 因此,用普通语句处理这样的事情是不可能的
myBatch.bat "&"^&
每一行都失败,因为cmd.exe试图执行一个&号(%1的内容是“&”&)
set var=%1
set "var=%1"
set var=%~1
set "var=%~1"
但是存在一个临时文件的解决方案
@echo off
SETLOCAL DisableDelayedExpansion
SETLOCAL
for %%a in (1) do (
set "prompt=$_"
echo on
for %%b in (1) do rem * #%1#
@echo off
) > param.txt
ENDLOCAL
for /F "delims=" %%L in (param.txt) do (
set "param1=%%L"
)
SETLOCAL EnableDelayedExpansion
set "param1=!param1:*#=!"
set "param1=!param1:~0,-2!"
echo %%1 is '!param1!'
诀窍是在rem语句后启用echo并展开%1(也适用于%2 ..% *)。 但是为了能够重定向echo on的输出,您需要两个for - loop。
额外的字符* #用于安全对抗/?(有助于快速眼动)。 或者行尾的插入符号^可以作为多行字符。
FOR /F应关闭延迟展开,否则包含“!”的内容将被销毁。 在删除param1中的额外字符后,您就得到了它。
要以安全的方式使用param1,请启用延迟扩展。
编辑:一条注释到%0
%0包含用于调用批处理的命令,也像FoO.BaT中一样保留大小写 但是在调用函数%0之后,也在%~0中包含函数名(或者更好的是用于调用函数的字符串)。 但是使用%~f0,您仍然可以找回文件名。
@echo off
echo main %0, %~0, %~f0
call :myLabel+xyz
exit /b
:MYlabel
echo func %0, %~0, %~f0
exit /b
输出
main test.bat, test.bat, C:\temp\test.bat
func :myLabel+xyz, :myLabel+xyz, C:\temp\test.bat
如果参数在包含空格的引号中,%*将无法正确工作。 我发现的最佳解决方案是使用一个连接所有参数的循环:https://serverfault.com/a/22541
set args=%1
shift
:start
if [%1] == [] goto done
set args=%args% %1
shift
goto start
:done
(use %args% here)
上面的很多信息引导我进行了进一步的研究,最终得出了我的答案,所以我想贡献我所做的事情,希望它能帮助其他人:
我还想向批处理文件传递不同数量的变量,以便在文件中处理它们。 我可以使用引号将它们传递给批处理文件 我希望他们处理类似于下面-但使用循环而不是手动写入:
所以我想执行这个:
prog_ZipDeleteFiles.bat "_appPath=C:\Services\Logs\PCAP" "_appFile=PCAP*.?"
通过for循环的魔力在批处理文件中做到这一点:
set "_appPath=C:\Services\Logs\PCAP"
set "_appFile=PCAP*.?"
我遇到的问题是,我使用for循环的所有尝试都不起作用。下面的例子:
for /f "tokens* delims= " in %%A (%*) DO (
set %%A
)
会这样做:
set "_appPath=C:\Services\Logs\PCAP"
而不是:
set "_appPath=C:\Services\Logs\PCAP"
set "_appFile=PCAP*.?"
即使在设置之后
SETLOCAL EnableDelayedExpansion
原因是for循环读取了整行,并在循环的第一次迭代中将第二个参数赋值给%%B。因为%*表示所有的参数,所以只需要处理一行——因此只会发生一次for循环。事实证明,这是故意的,而我的逻辑是错误的。
因此,我不再尝试使用for循环,而是通过使用if、shift和goto语句来简化我试图做的事情。同意,这有点黑,但它更适合我的需要。我可以遍历所有参数,然后在处理完所有参数后使用if语句退出循环。
我想要实现的目标是:
echo on
:processArguments
:: Process all arguments in the order received
if defined %1 then (
set %1
shift
goto:processArguments
) ELSE (
echo off
)
更新-我不得不修改如下,当我试图引用%1并以这种方式使用shift时,我暴露了所有的环境变量:
echo on
shift
:processArguments
:: Process all arguments in the order received
if defined %0 then (
set %0
shift
goto:processArguments
) ELSE (
echo off
)