如何在调用CMD批处理脚本标签时使用超过9个参数?

34

我想知道如何在批处理脚本中调用超过9个参数来调用标签。例如,以下示例显示我已分配了12个参数,并尝试回显所有参数。

CALL:LABEL "one" "two" "three" "four" "five" "six" "seven" "eight" "nine" "ten" "eleven" "twelve"
PAUSE
GOTO:EOF


:LABEL
echo %1
echo %2
echo %3
echo %4
echo %5
echo %6
echo %7
echo %8
echo %9
echo %10
echo %11
echo %12

%10、%11和%12的输出结果最终为one0 one1 one2。我尝试使用花括号、方括号、引号、单引号将数字括起来,但都没有成功。


2
我想补充一下,SHIFT 命令可以与 /N 开关一起使用,以选择从哪个参数开始。例如,如果你使用 SHIFT 命令访问了第 10 个参数,为了再次访问第 0 个参数(当前运行的批处理脚本的绝对路径),你可以使用 SHIFT /N 0 命令将自己重置回原始的 0-9 个参数。 - Anthony Miller
可能是如何将超过9个参数传递给批处理文件的重复问题。 - Badasahog
这个答案在另一个解决方案中非常出色,它允许任意数量的参数,并将其保存以供以后使用。 - Gigamosh57
7个回答

36

如果你想使用超过九个参数,可以使用 shift 命令
(实际上,如果计算上 %0 参数,则可以超过 10 个参数)

你可以使用 shift 命令创建一个批处理文件,可以接受超过 10 个批处理参数。如果在命令行上指定了超过 10 个参数,则出现在第十个(%9)之后的参数将逐个移入 %9 中。

你可以使用循环、在移位前存储变量或像这样快速完成:

@echo off
CALL:LABEL "one" "two" "three" "four" "five" "six" "seven" "eight" "nine" "ten" "eleven" "twelve"
PAUSE
GOTO:EOF

:LABEL
:: print arguments 1-9
echo %1
echo %2
echo %3
echo %4
echo %5
echo %6
echo %7
echo %8
echo %9

:: print arguments 10-11
shift
shift 
echo %8
echo %9

:: print argument 13
shift
echo %9

如果您有很多参数,可以用循环替换移动命令。下面的for循环执行九次shift,这样%1将成为第十个参数。

@for /L %%i in (0,1,8) do shift

但在这种情况下,%7、%8、%9是指旧值,而不是“十”、“十一”等。 - iAmLearning
1
请看:https://dev59.com/l2Ei5IYBdhLWcg3wD4gu - iAmLearning

11

如果有所帮助,我愿意提供帮助。




Set a=%1 & Set b=%2 & Set c=%3 & Set d=%4 & Set e=%5 & Set f=%6 & Set g=%7 & Set h=%8 & Set i=%9
Shift & Shift & Shift & Shift & Shift & Shift & Shift & Shift & Shift
Set j=%1 & Set k=%2 & Set l=%3 & Set m=%4 & Set n=%5 & Set o=%6 & Set p=%7 & Set q=%8 & Set r=%9
Shift & Shift & Shift & Shift & Shift & Shift & Shift & Shift & Shift
Set s=%1 & Set t=%2 & Set u=%3 & Set v=%4 & Set w=%5 & Set x=%6 & Set y=%7 & Set z=%8

我只需要把这个放在使用>9个参数的.bat或子程序的顶部,然后您就可以使用%a%%z%代替不存在的%26

这很丑陋,最初我把它都放在一行上,就像这样

Set a=%1 & Shift & Set b=%1 & Shift &...

这样,它只在一行上,并且很快就会隐藏在编辑器的边缘后面,但显然Shift不会生效直到下一个真正的行;所有变量都设置为第一个参数。

如果你想知道为什么这样做而不是使用循环,除非有人向我展示您可以创建一种类似的映射或数组,否则我需要在单行命令中使用变量,而不是逐个地echo(或者执行其他操作):

::example; concatenate a bunch of files
Set output=%1
Shift
<insert above behemoth>
type %a% %b% %c% %d% %e% %f% 2>NUL > %output%

该死,bash比这容易多了。
cat ${@:2} > "$1"

使用“Set a =%1 ... Shift”方法,我在批处理文件中成功地处理了18个参数的单个命令行,以便一起使用。 - Polymath
它们是如何连接的?使用&符号还是我没有想到的其他方式? - Hashbrown
2
唯一需要微调的是删除参数和&之间的空格。例如:Set a=%1& Set b=%2& Set c=%3& ... 否则,在替换时会附加不必要的空格到值上。 - Polymath

9

假定我们在此处使用的是最新版本的CMD,我很惊讶地发现没有人发布以下内容,这可以轻松处理任意数量的参数,而无需使用笨拙的 shift 命令:

rem test.bat
call :subr %*
exit /b

:subr
for %%A in (%*) do (
    echo %%A
)
exit /b

你也可以在“main”中使用相同的技术。这样,你就不会在处理它们时吃掉你的参数,并且无需使用“shift”,这意味着如果你有复杂的调用选项并且它使你的脚本逻辑更简单,你可以一致地循环遍历参数列表多次。显然,如果你循环遍历超过一次,它会增加计算复杂度以换取可读性,但是Bash和CMD都不是为了速度而建立的(至少我听说过的情况如此),因此没有必要尝试通过一次性进行设置来进行优化,假设n小于100左右。以下是一些示例输出:
C:\tmp>test.bat one two three four five six seven eight nine ten eleven
one
two
three
four
five
six
seven
eight
nine
ten
eleven

编辑 - 假设任何人正在处理另一个列表的参数,并且工作的一部分是嵌套的,那么重要的是使用一个中间的CALL来允许当前正在处理的参数被传递到内部循环; 简单地执行set intermediary=%%OUTER似乎只会将intermediary设置为空字符串,所以最简单的方法是这样做:

setlocal enabledelayedexpansion
rem ^ in my experience, it's always a good idea to set this if for-loops are involved
for /f %%L in (file.txt) do (
    call :inner %%L
)
exit /b

:inner
for %%A in (%*) do (
    if %%A EQU %~1 call dosomething.bat %~1        
)
exit /b

编辑2 - 如果您希望在此处添加shift方法,即通过将除第一个参数外的所有参数传递给子程序使用shift,然后使用call:subroutine%*,请注意%*实际上按顺序将所有原始参数提供给您,而无视任何移动。这很遗憾,因为没有本地语法(至少我不知道)可以将某个参数之后的所有参数分组,就像人们可能会期望%3*执行的那样。


8

这是使用 shift 命令的另一种方式。

请注意,在这种情况下,您可以使用可变数量的参数。

@ECHO OFF
CALL:LABEL "one" "two" "three" "four" "five" "six" "seven" "eight" "nine" "ten" "eleven" "twelve"
PAUSE
GOTO:EOF

:LABEL
echo %1
shift
if not [%1]==[] GOTO LABEL

3

在批处理文件中,你不能使用超过10个(0到9)可访问参数(%0是批处理文件本身)。但是,使用shift命令可以让你“左移”参数,并访问第9个参数之后的参数。如果你使用shift命令三次,你应该会得到%7、%8和%9,它们分别包含“ten”、“eleven”和“twelve”。


0

我知道这篇文章有点老了,但我想为其他正在谷歌搜索的人更新一下。

对于任何好奇的人,我创建了一个不错的动态和紧凑的方法来实现这个,所以你可以拥有可变数量的参数。

SETLOCAL ENABLEDELAYEDEXPANSION
:ARG
set /A Count+=1
echo !Count!
if "%~1"=="" (
    GOTO ENDARGS
) else (
    <Do Something, call variables with !VarName! instead of %VarName%>
)
shift
GOTO ARG
:ENDARGS
ENDLOCAL

kkk的答案也可以工作

如果有人有任何改进,请告诉我。我尝试使用以下也被接受的方法。但是对于使用此方法并尝试执行像我这样疯狂的操作,例如具有超过27个参数的人,这不起作用。它在27个之后停止。或者至少这就是我经历的,如果您有其他经历,请告诉我。

for %%a in (%*) do (
    <Do Something>
)

0

Hashbrown有一个完美简单的答案来移位10..n在SETting变量上,Polymath有一个完美的评论如何避免末尾的空格(&技巧)。

这是我的答案,设置1..18个参数,避免空格,并从输入参数中删除"my param value X"引号(~技巧)。

@rem must shift 10..n input params, avoid whitespaces by using "~1& .."
@set p1=%~1& set p2=%~2& set p3=%~3& set p4=%~4& set p5=%~5& set p6=%~6& set p7=%~7& set p8=%~8& set p9=%~9
@Shift & Shift & Shift & Shift & Shift & Shift & Shift & Shift & Shift
@set p10=%~1& set p11=%~2& set p12=%~3& set p13=%~4& set p14=%~5& set p15=%~6& set p16=%~7& set p17=%~8& set p18=%~9

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接