如何在批处理文件中使用嵌套变量抽象?

时间:2016-10-22 01:11:10

标签: batch-file cmd

我试图编写自己的批处理文件来切换npm版本(只是为了好玩)。

@echo off
for /f "delims=" %%i in ('npm -v') do set output=%%i
move "%NPM_PATH%" "%NPM_PATH%-%output%"

FOR %%A IN (%*) DO (
  IF "%%A"=="--change" (
    SETLOCAL EnableDelayedExpansion

    SET /A c=1
    ECHO "ID : VERSION"
    ECHO -------------------------

    FOR /F "tokens=*" %%F in ('dir /on /b /a:d /p "%NPM_DIR%"') DO ( 
      ECHO !c! : %%F
      SET dir_!c!=%%F
      SET /a c=c+1   
    )

    set /p id="enter version ID: (e.g. !dir_1! enter 1):"
    set target_dir= "dir_!id!"
    echo !target_dir!
  )
)

我可以回应出我想抽象的正确变量。

但是如何实际输出!target_dir!的值?

示例:

用户选择1

echo !target_dir!会将dir_1打印到屏幕上。

但是,当我使用下一个echo !dir_1!时,会打印npm-4.0.0

当用户输入npm-4.0.0时,我现在如何输出1

2 个答案:

答案 0 :(得分:1)

我建议使用以下代码,并在代码中使用Aacini提供的第二个建议以及其他一些改进:

@echo off
for /F "delims=" %%I in ('npm.bat -v') do set "output=%%I"
move "%NPM_PATH%" "%NPM_PATH%-%output%"

for %%A in (%*) do (
    if "%%A" == "--change" (
        setlocal EnableDelayedExpansion
        cls
        set "Count=1"
        echo ID : VERSION
        echo -------------------------

        for /F "tokens=*" %%F in ('dir /A:D /B /ON "%NPM_DIR%"') do (
            if !Count! LSS 10 (
                echo  !Count! : %%F
            ) else (
                echo !Count! : %%F
            )
            set "dir_!Count!=%%F"
            set /A Count+=1
        )

        echo.
        set "id=1"
        set /P "id=Enter version ID: (e.g. !dir_1! enter 1): "
        for %%I in (!id!) do set "TargetDir=!dir_%%I!"
        echo !TargetDir!
        endlocal
    )
)

for %%I in (!id!) do set "TargetDir=!dir_%%I!"dir_X分配名称为X且环境变量id中存储的输入数字为set variable="value"的环境变量的值,详细解释为{{3} }}回答Aacini's

对于应用的改进,请参阅:

建议在set表示法中使用具有自解释名称的环境变量。这样做的好处是可以知道变量的用途,并且可以更轻松地搜索变量的所有实例。搜索名为/A的变量有点困难,因为单个字符经常出现在许多字符串中。

带有选项0的命令SET /A c=1表示下一步应解释为算术表达式。这意味着使用空格/制表符作为字符串分隔符将等号后的字符串拆分为字符串列表。可以解释为十进制,八进制或十六进制数的每个字符串都将转换为32位有符号整数。所有其他非运算符的字符串都被解释为变量的名称,其值应转换为32位有符号整数。如果变量不存在或者没有数字作为值,则SET "c=1"用于变量。然后计算算术表达式,并将结果从整数转换回字符串。最后,结果字符串被分配给左边是等号的环境变量。因此,1c进行了大量额外工作,但结果相同,将值为/A的字符串分配给名为set /A c=009的变量。因此,建议不要使用009为环境变量赋值,除非有很好的理由这样做,就像字符串实际上是一个数字的原始检查一样。注意:类似c的分配会导致错误消息,因为set c=009是无效的八进制数,set "id=1"未定义,或者在1已定义的情况下保留其当前值1}}工作。

当提示批处理用户输入字符串时,用户可以自由地点击 RETURN ENTER 而不输入任何内容。在这种情况下,环境变量保持其当前值,或者如果在提示用户之前未定义环境变量,则仍未定义。这解释了为什么在提示用户之前,!Count!存在于上面的批处理代码中。好吧,我们不会检查用户是否确实输入了一个号码,而且这个号码是否在FILTER_VALIDATE_EMAIL ... if (!filter_var($email, FILTER_VALIDATE_EMAIL) === false) { // insert record } else{ echo "not valid email"; } 范围内,但这可能不是必需的,尽管可能总是会出现输入错误。 / p>

答案 1 :(得分:0)

根据@Aacini,我只需更改此行:set target_dir= "dir_!id!"即可:for %%i in (!id!) do set target_dir=!dir_%%i!

See this question