我想知道在调用标签时如何在批处理脚本中调用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。我尝试过使用大括号,括号,引号,数字周围的单引号而没有任何运气。
如果您想使用更多9个参数,请使用shift
command。
(如果计算%0
参数,实际上超过10个参数)
您可以使用shift命令创建一个可以接受10个以上批处理参数的批处理文件。如果在命令行上指定了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
如果您有许多参数,可以用循环替换shift命令。以下for循环执行shift
九次,因此%1
将是第十个参数。
@for /L %%i in (0,1,8) do shift
这是使用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
假设我们在这里使用了最新版本的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 %*
尝试将除1st之外的所有参数传递给子例程 - 请注意它不会工作,因为%*
实际上按顺序给你所有的原始论点,不知道你做了什么改变。
这是一种耻辱,因为没有本地语法(我知道)可以将所有参数分组到某个参数之后,正如人们可能期望的那样,%3*
可以这样做。
批处理文件中不能有超过10个(0到9)可访问的参数(%0是批处理文件本身)。但是,使用shift
命令将允许您“左移”您的参数,并访问超出第9个参数的那些参数。如果你这样做三次,你应该得到%7,%8和%9包含“十”,“十一”和“十二”。
如果它有助于任何人,只要将我的帽子扔进戒指
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
我只是把它放在.bat
或子程序的顶部,将使用> 9 args,然后你可以使用%a%
通过%z%
而不是%1
到不存在的%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"