2009-08-18 147 views
77

只是将一些shell脚本转换为批处理文件,并且有一件事我无法找到......并且这是一个简单的命令行参数数量。批处理文件 - 命令行参数的数量

例如。如果您有:

myapp foo bar 

在壳牌:

  • $# - > 2
  • $ * - > FOO吧
  • $ 0 - > MYAPP
  • $ 1 - “FOO
  • $ 2 - > bar

在批次

  • ?? - > 2 < ----什么命令?!
  • %* - > FOO吧
  • %0 - > MYAPP
  • %1 - >富
  • %2 - >酒吧

所以我环顾四周,并任我在寻找错误的地方或我是盲目的,但我似乎无法找到一种方法来获得通过的命令行参数的数量的计数。

是否有类似于shell的“$# “批处理文件?

ps。我发现的最接近的是遍历%1s并使用'shift',但在脚本后面需要引用%1,%2等,所以这没什么用。

+0

您的字符串是'2 MYAPP富bar'? – PsychoData 2014-02-05 00:29:39

+2

建议:不要将sh转换为BAT。相反,请下载cygwin并使用它。即您的sh脚本将在Windows机器上工作。你不需要翻译每一个嘘到英美烟草! – 2015-04-15 16:09:52

回答

81

谷歌上搜索了一下让你从wikibooks以下结果:

set argC=0 
for %%x in (%*) do Set /A argC+=1 

echo %argC% 

似乎cmd.exe已经从旧的DOS天进化了一下:)

+7

请注意,这个'for'的变体只适用于看起来像文件名的参数,而不是像' - ?'这样的选项字符串。使用引号('%for %%'in(“%*”)...')适用于像' - ?'这样的参数,但由于嵌套引号而引用的参数失败。唯一强大的方式似乎涉及'转移'... – 2013-08-23 12:35:36

+1

对不起,downvoted因为@FerdinandBeyer说 – n611x007 2013-08-23 18:50:42

33

你往往处理的参数的个数与这种逻辑:

IF "%1"=="" GOTO HAVE_0 
IF "%2"=="" GOTO HAVE_1 
IF "%3"=="" GOTO HAVE_2 

如果你有超过900名的参数,那么你拧这种方法虽然。有各种创建计数器的黑客,你可以找到here,但要警告这些不适合胆小的人。

+3

你仍然可以使用'shift'来计算超过9 ...并且没有10行相同的代码。 – Joey 2009-09-30 13:13:47

18

以下功能:getargc可能是您正在寻找的。

@echo off 
setlocal enableextensions enabledelayedexpansion 
call :getargc argc %* 
echo Count is %argc% 
echo Args are %* 
endlocal 
goto :eof 

:getargc 
    set getargc_v0=%1 
    set /a "%getargc_v0% = 0" 
:getargc_l0 
    if not x%2x==xx (
     shift 
     set /a "%getargc_v0% = %getargc_v0% + 1" 
     goto :getargc_l0 
    ) 
    set getargc_v0= 
    goto :eof 

它基本上一次迭代在列表上(这是本地的功能,使该转变将不会影响列表回到主程序),计数,直到用完。

它还使用了一个漂亮的技巧,传递函数设置的返回变量的名称。

主程序只是说明了如何把它和回声的参数之后,以确保它们是不变:

C:\Here> xx.cmd 1 2 3 4 5 
    Count is 5 
    Args are 1 2 3 4 5 
C:\Here> xx.cmd 1 2 3 4 5 6 7 8 9 10 11 
    Count is 11 
    Args are 1 2 3 4 5 6 7 8 9 10 11 
C:\Here> xx.cmd 1 
    Count is 1 
    Args are 1 
C:\Here> xx.cmd 
    Count is 0 
    Args are 
C:\Here> xx.cmd 1 2 "3 4 5" 
    Count is 3 
    Args are 1 2 "3 4 5" 
+0

你如何根据这个改变流程? (可能是一个不同的问题,但我认为一个简短的例子在这里也会很方便!) – n611x007 2013-08-23 18:53:43

+0

@ n611x007其中'echo Count是%argc%'你可以插入你自己的代码来检查计数是否正确,然后继续。 – kenny 2017-03-27 14:14:16

6

试试这个:

SET /A ARGS_COUNT=0  
FOR %%A in (%*) DO SET /A ARGS_COUNT+=1  
ECHO %ARGS_COUNT% 
+5

是这个答案不同于[@nimrod one](http://stackoverflow.com/a/1292094/505893) ?... – bluish 2012-05-17 13:27:48

+0

查看@FerdinandBeyer在nimrodm的评论。不会因为你有21代表而失望8) – n611x007 2013-08-23 18:51:56

5

如果参数的数量应为一个确切的数字(9小于或等于),那么这是一个简单的方法来检查它:

if "%2" == "" goto args_count_wrong 
if "%3" == "" goto args_count_ok 

:args_count_wrong 
echo I need exactly two command line arguments 
exit /b 1 

:args_count_ok 
2

避免了使用任一shift或在for周期尺寸和可读性的成本。

@echo off 
setlocal EnableExtensions EnableDelayedExpansion 
set /a arg_idx=1 
set "curr_arg_value=" 
:loop1 
if !arg_idx! GTR 9 goto :done 
set curr_arg_label=%%!arg_idx! 
call :get_value curr_arg_value !curr_arg_label! 
if defined curr_arg_value (
    echo/!curr_arg_label!: !curr_arg_value! 
    set /a arg_idx+=1 
    goto :loop1 
) 
:done 
set /a cnt=!arg_idx!-1 
echo/argument count: !cnt! 
endlocal 
goto :eof 

:get_value 
(
    set %1=%2 
) 

输出:

count_cmdline_args.bat testing more_testing arg3 another_arg 

%1: testing 
%2: more_testing 
%3: arg3 
%4: another_arg 
argument count: 4 

编辑:这里使用的 “特技” 涉及:

  1. 构建一个代表当前评估的命令行参数变量的字符串(即,“% 1" ,‘使用含有百分号(%%)和每次循环迭代计数器变量arg_idx字符串%2’等)。

  2. 存储该字符串转换成可变curr_arg_label

  3. 将该字符串(!curr_arg_label!)和返回变量的名称(curr_arg_value)传递给原始子程序get_value

  4. 在子程序的第一个参数的(%1)值被用在分配(set)和在右侧的第二参数的(%2)值的左侧。但是,当第二个子程序的参数被传递时,它将被命令解释器解析为主程序的命令行参数的值。也就是说,传递的内容不是,例如“%4”,但是第四个命令行参数变量保存的值(示例用法中的“another_arg”)。

  5. 然后,将给予子程序的变量作为返回变量(curr_arg_value)进行测试,以确定是否未定义,如果当前评估的命令行参数不存在,则会发生这种情况。最初,这是将方括号中包含的返回变量的值与空方括号(这是我知道测试程序或子程序参数可能包含引号的唯一方式,并且是从试错阶段遗漏的剩余部分)的比较,但是自从现在被固定到现在。

+1

虽然这段代码可能回答这个问题,但提供关于如何和/或为何解决问题的附加背景将会提高答案的长期价值。 – thewaywewere 2017-06-09 02:35:11

+0

@thewaywewere谢谢,我一直忘记,对于很多人(可能是大多数人),最好是有一个文字说明,而不是“不言自明”的代码。 – 2017-07-16 11:27:21