在FOR语句中的变量上使用子字符串

时间:2019-05-03 09:42:43

标签: windows batch-file

在FOR语句中的每个变量中测试字符1的正确语法是什么?我的目标是从命令行中识别以字符1的破折号开头的变量。

这是示例命令行:m

mysample.bat -p1=1 -p2=2 -p3="abc" myfile

这是我尝试的,使用%%~1的子字符串语法:

setlocal enabledelayedexpansion
(for %%i in (%*) do if not %%~1:~0,1%=='-' set "filename=%%~i")>nul

这将显示以下错误消息:

  

“在批处理参数替换中以下路径运算符的使用无效:%〜i”)> nul“

1 个答案:

答案 0 :(得分:0)

让我们首先看看mysample.bat仅包含

@echo off
for %%I in (%*) do echo %%I

以及在包含mysample.bat命令行的目录中的命令提示符窗口中运行时的输出:

mysample.bat -p1=1 -p2=2 -p3="abc" myfile

输出为:

-p1
1
-p2
2
-p3
"abc"
myfile

因此, FOR 将等号解释为参数分隔符,例如空格字符或逗号和其他一些字符。

在代码检查是否使用至少一个参数调用了批处理文件后,将分配给环境变量的 last 参数的简单解决方案是:

set "FileName="
for %%I in (%*) do set "FileName=%%~I"
if defined FileName echo File name is: %FileName%

输出为:File name is: myfile

但是使用以下命令调用批处理文件呢?

mysample.bat -p1=1 myfile -p2=2 -p3="abc"

好吧,File name is: abc

的输出错误也就不足为奇了。

使用命令 SHIFT 怎么办?

@echo off
set "ArgNumber=1"
:ArgLoop
if "%~1" == "" goto :EOF
echo Argument %ArgNumber% is: "%~1"
set /A ArgNumber+=1
shift
goto ArgLoop

使用上面的参数列表运行批处理文件的输出为:

Argument 1 is: "-p1"
Argument 2 is: "1"
Argument 3 is: "myfile"
Argument 4 is: "-p2"
Argument 5 is: "2"
Argument 6 is: "-p3"
Argument 7 is: "abc"

因此,cmd.exe还将等号解释为=上的参数分隔符,而不位于双引号引起来的参数字符串中。好吧, FOR cmd.exe的内部命令,因此相同的代码用于解释批处理文件的参数列表以及 FOR < / strong>。

cmd.exe支持环境变量的字符串替换。不能将它们应用于批处理文件参数或分配给 FOR 循环变量的字符串上。

因此,让我们看一下真正评估参数的批处理文件代码:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FileName="
rem Delete all environment variables of which name starts with Parameter.
for /F "delims==" %%I in ('set Parameter 2^>nul') do set "%%I="

:ArgLoop
set "Argument=%~1"
if defined Argument (
    if /I "%Argument:~0,2%" == "-p" (
        set "Parameter %Argument:~2%=%~2"
        shift
    ) else if not defined FileName (
        set "FileName=%~1"
    ) else (
        echo WARNING: Unknown argument: "%~1"
    )
    shift
    goto ArgLoop
)
rem The current argument could be "" which is an empty argument.
rem The current argument could be also just " on being last argument.
rem Don't break the argument loop on such an empty argument, but
rem instead just ignore this empty argument with a warning.
set Argument=%1
if defined Argument (
    echo WARNING: Empty argument: %Argument%
    shift
    goto ArgLoop
)

echo/
if defined FileName echo File name is: "%FileName%"
for /F "tokens=1* delims==" %%I in ('set Parameter 2^>nul') do echo %%I is: "%%~J"
endlocal

让我们使用命令行运行该批处理文件:

mysample.bat "" -p1="First Paramter" myfile -p2 "2nd parameter" What's that -p3,ThirdParameter -p4 Fourth value! "

输出为:

WARNING: Empty argument: ""
WARNING: Unknown argument: "What's"
WARNING: Unknown argument: "that"
WARNING: Unknown argument: "value!"
WARNING: Empty argument: "

File name is: "myfile"
Parameter 1 is: "First Paramter"
Parameter 2 is: "2nd parameter"
Parameter 3 is: "ThirdParameter"
Parameter 4 is: "Fourth"

我认为此输出很好。它会向用户通知明显错误的指定参数,但仍会处理有效参数。

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • rem /?
  • set /?
  • setlocal /?
  • shift /?

也请阅读有关Using Command Redirection Operators的Microsoft文章,以获取2>nul的解释。当Windows命令解释器在执行命令之前处理此命令行时,重定向操作符>必须在 FOR 命令行上使用脱字符号^进行转义,才能被解释为文字字符。 FOR ,它将在后台启动的单独命令进程中执行嵌入式set命令行。