2012-10-20 204 views
1

我试图将一些可选参数添加到批处理文件,但遇到麻烦,因为SHIFT命令不会影响所有参数变量%*SHIFT不会影响%*

有谁知道如何我可以允许可选的批处理文件参数,如果我必须使用%*

例如,一个简单的例子,仅仅打印参数的屏幕,并没有新的线路,使用一个可选的参数,以确定哪些:

@echo off 
if (%1)==() goto usage 
if (%1)==(/n) goto noeol 
goto eol 

:eol 
    echo %* 
    goto :eof 

:noeol 
    shift 
    call showline %* 
    goto :eof 

:usage 
    echo Prints text to the screen 
    echo > %0 [/n] TEXT 
    echo /n to NOT print a new-line at the end of the text 
    goto :eof 
+0

我刚刚被这个烧伤了。 Windows SHIFT的确很臭。 – Core

回答

3

如你所知,shift有没有影响%*,但你可以构造一个%*等价物。

我们称以下line.bat

@echo off 
set line=%1 
:loop 
shift 
if not "%1"=="" (
    set line=%line% %1 
    goto :loop 
) 

echo %%* = %* 
echo line = %line% 

如果在键入以下命令(注意:3之间的双空间和4)

line 1 2 3 4 bla dee dah 

你会得到以下输出

%* = 1 2 3 4 bla dee dah 
line = 1 2 3 4 bla dee dah 

请注意,%*保留多个空格,而使用%n表示法不会。


使用类似这样的东西,您可以允许您的用户以任意顺序放置其参数。

:loop 
    :: Single variable parameters 
    if "%1"=="something" set something=true 
    :: Multi variable parameters 
    if "%~1"=="/source" shift & set source=%1 
    shift 
if not "%~1"=="" goto :loop 

注意的是,在多变量参数声明我包括一个shift语句和由符号(&)分隔的一个set语句。 &告诉命令处理器一个单独的命令被执行。


编辑:

FYI:我检查变量的内容时,建议双引号。 通常你可以使用任何字符,你甚至不需要使用两个,因为他们只是在那里,以确保一个空的变量不会导致错误。例如,当%1为空且您做了if not hello==%1 call :sub时,命令处理器将看到此if not hello== call :sub并将hellocall比较,然后尝试执行:sub并引发错误。在这种情况下,if not xhello==x%1 call :subif not "hello"=="%1" call :sub一样好,因为空的%1将导致命令处理器看到if not xhello==x call :sub。比双引号其他

使用字符会如果变量包含任何特殊字符引起问题。

使用括号作为变量分隔符(如(%1))可能会导致问题。例如,(特殊)管道字符在括号内不会很好,转义字符似乎消失了,既不是正常字符也不是逃逸字符。

括号也是特殊字符,它们本身被设计用于对不同的代码行进行分组和分隔,并且可能并不总是按预期行事。

最后,双引号本身是特殊字符专门设计用于包围其他特殊字符,允许它们充当普通字符。这就是为什么你可能会看到变量没有被引用,然后再次引用,如此。

set var="%~1" & REM This sort of thing is used to insure that a variable is quoted. 
       REM %~1 unquotes %1 if it is already quoted, and leaves it alone if 
       REM %1 is not quoted. 

set "var=%~1" & REM This code assumes that `%1` contains special characters and 
       REM like before unquotes a quoted %1, but leaves the variable itself 
       REM unquoted. The double-quotes surrounding the variable and data 
       REM protects the command processor from any special characters that 
       REM exist in the data. Remember that anytime you reference `%var%`, 
       REM you will need to also surround the variable and data with 
       REM double-quotes. 

快速检查报价是if exist %1 if %1==%~1 echo Unquoted

+0

非常聪明。 ☺ – Synetech

0

我喜欢詹姆斯的解决方案,因为它不需要任何用户特别的东西(这总是可取的),但我只是想到另一种方式;把参数放在引号中,并在运行时剥去它们:

Print.bat: 

@echo off 
if (%1)==() goto usage 
if (%1)==(/n) goto noeol 
goto eol 

:eol 
      :: Use %~1 to 
    echo %~1 
    goto :eof 

:noeol 
    shift 
    call showline %~1 
    goto :eof 

:usage 
    echo Prints text to the screen 
    echo > %0 [/n] TEXT 
    echo /n to NOT print a new-line at the end of the text 
    goto :eof 



Results: 

    C:\>print.bat "foo bar baz" 
    foo bar baz 

    C:\>print.bat /n "foo bar baz" 
    foo bar baz 
    C:\> 
+0

仅供参考:在检查变量内容时,我建议使用双引号'“”',而不是括号'()'。查看我的答案的最后编辑为什么。 –

+0

@JamesK,我通常对我的DOS和更简单的Windows批处理文件使用括号,因为它们对引用的参数引起较少麻烦,并且对它们具有“封闭”意义。但是,为了兼容性和安全性,[最好使用括号或大括号](http://stackoverflow.com/questions/2541767/what-is-the-proper-way-to-test-is-variable-is-因为命令解释器不会为它们指定任何特殊的含义,就像它对引号和括号所做的那样,它是空批量文件如果不是1/2541820#comment17636634_2541820)。 – Synetech