【问题标题】:Windows Batch Command : How to dereference FOR loop variable to check if that variable is SET in Environment VariableWindows 批处理命令:如何取消引用 FOR 循环变量以检查该变量是否在环境变量中设置
【发布时间】:2014-12-14 23:38:18
【问题描述】:

我正在编写一个批处理命令脚本,其中检查环境变量。我需要通过传递所有必需的变量来编写一个 FOR 循环,然后验证它是否已定义,如果未定义,则提示该键的值并永久设置该变量。

问题是我无法取消引用循环变量并在环境变量中检查它。

示例代码如下:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%G IN (JBOSS_HOME, JAVA_HOME, ANT_HOME, PERFORCE_PATH, P4CLIENT) DO (
  ECHO.
  ECHO. Loop Item : %%G
  :: Call a function by sending each value to check if it is set in ENVIRONMENT Variables, if not then add it persistently.
  CALL:validateAndUpdate %%G
)
GOTO:EOF

:validateAndUpdate
  :: Now I have to check if passed value is available in ENVIRONMENT variable or not
  :: echo %~1 will print value like JBOSS_HOME 
  :: Below IF condition always substitues to IF ("JBOSS_HOME" == []) and it always returns true
  :: but could not find syntax to use it to DE-reference and check if that key is set.
  :: Ex: IF %JBOSS_HOME% == []

  IF ("%~1" == []) (
    ECHO.
    ECHO. %~1 is empty
    SET /p value="Enter value for '%~1' : "

    :: Set that key value pair persistently using SETX
    SETX %~1 "%value%" 
  ) ELSE (
    ECHO.
    ECHO. %~1 is available as ENVIRONMENT variable
  )

GOTO:EOF

ENDLOCAL

【问题讨论】:

  • 我得到了一半的溶液,而不是IF ("%~1" == [])需要使用IF("!%~1!" == [])
  • 即使未定义变量,它也会返回 true。也尝试了IF ("!%~1!" == ""),但它仍然是ELSE 条件
  • 应该是IF "!%~1!"=="" 注意没有== 周围的空格,没有括号。那!%~1!是变量value%~1是变量name
  • @JosefZ,感谢您的回复,我尝试使用IF !%~1!=="" ( 没有帮助,它仍然进入 ELSE 条件
  • 仔细阅读:IF "!%~1!"=="" 不是IF !%~1!=="" 注意双引号

标签: windows batch-file for-loop command


【解决方案1】:

要检查是否定义了变量,请在 if 语句中使用 defined 关键字。 help if 了解更多信息。

如果我可以提出另一个建议,最好为用户显示一个文件夹选择器,而不是让他手动输入路径名。为此,请使用 .bat 扩展名保存此概念证明并尝试一下。看看它是否如你所愿:

@if (@a==@b) @end   /* JScript multiline comment

:: based on https://stackoverflow.com/a/15906994/1683264
:: batch portion

@echo off
setlocal enabledelayedexpansion

for %%G in (windir, temp, foo, bar) do (
    if not defined %%G (
        call :chooser %%G "Locate directory for %%G."
    ) else echo %%G is already defined as !%%G!
)

goto :EOF

:chooser <var_to_set> <dialog_title>
for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%~2"') do (

    rem :: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    rem :: Remove the "echo" from this next line when you are satisfied
    rem :: that it will do what you intend.
    rem :: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    echo setx %~1 "%%~I"

)
goto :EOF

:: JScript portion */

var shl = new ActiveXObject("Shell.Application");
var folder = shl.BrowseForFolder(0, WSH.Arguments(0), 0, 0x00);
WSH.Echo(folder ? folder.self.path : '');

在您对模拟结果满意后,从:chooser 子例程中删除echo

有关从 .bat 脚本启动文件或文件夹选择器的更多方法,请参阅 this page,有关 JScript/批处理混合的更多详细信息和更多示例,请参阅 this GitHub Gist

【讨论】:

  • 感谢这个示例,虽然它不是我所需要的,但我可以在需要选择文件夹的情况下使用它。因为一些环境变量只是键值对,而不是文件夹。
【解决方案2】:
@echo off
    setlocal enableextensions disabledelayedexpansion

    for %%g in (JBOSS_HOME, JAVA_HOME, ANT_HOME, PERFORCE_PATH, P4CLIENT) do (
        echo(
        echo Testing %%g
        if defined %%g (
            echo %%g is available as ENVIRONMENT variable
        ) else (
            echo %%g is empty
            set /p "value=Enter value for '%%g' : " && (
                setlocal enabledelayedexpansion
                for /f "delims=" %%v in ("!value!") do (
                    endlocal 
                    SETX %%g "%%v"
                )
            )
        )
    )

如前所述,if defined varname 是检查变量是否已定义的“正确”方法。

【讨论】:

  • 只是好奇,Google 并没有说明此事。在需要!var! 之前避免enabledelayedexpansion 有什么好处;或者,让整个脚本在enabledelayedexpansion 下运行有什么缺点?如果我的脚本不包含任何延迟变量,我通常不包含 enabledelayedexpansion。但是,如果至少有一个延迟变量,即使它在脚本的末尾,我总是将enabledelayedexpansion 戳在顶部@echo off 的下方并将其留在那里。为什么这很糟糕?我这辈子一直在说谎吗?
  • @rojo,在批处理文件中运行:setlocal enabledelayedexpansionset "data=this is a test !!!"echo !data!。你会看到! 成为一个额外的问题来处理。
  • 谢谢!顺便说一句,你头像上的帽子不错。
猜你喜欢
  • 1970-01-01
  • 2016-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-03
相关资源
最近更新 更多