What syntax will check if a variable name containing spaces is defined?

前端 未结 4 774
你的背包
你的背包 2021-01-05 11:45

Windows user defined environment variable names can contain any character except =.

Special characters can be included by escaping them. A simpler metho

相关标签:
4条回答
  • 2021-01-05 12:00

    The other way is to reassign it to another variable (one without spaces) and test that. See here:

    rem Prepare ONLY variable 'a b'
    set "a b=123"
    echo [a b]=%a b%
    
    rem This will ouput: [a b] is defined
    set var=%a b%
    if defined var (
      echo [a b] is defined
    ) else (
      echo [a b] is not defined
    )
    
    rem This will output: [c d] is not defined
    set var=%c d%
    if defined var (
      echo [c d] is defined
    ) else (
      echo [c d] is not defined
    )
    
    0 讨论(0)
  • 2021-01-05 12:00

    I do it by defining a flag as TRUE if needed...

    rem /* sample code */
    set VAR_SET=
    if <some condition> set VAR_SET=TRUE&set VAR=this data has spaces
    
    rem /* test for VAR_SET using 'if defined' */
    if defined VAR_SET (
      rem /* do something with the other data in the variable %VAR% */
    )
    
    rem /* clear the flag */
    set VAR_SET=
    
    0 讨论(0)
  • 2021-01-05 12:22

    Interessting question (I love this syntax base questions).

    Obviously you know how to check it with delayed expansion and also FOR-parameters works.

    @echo off
    setlocal
    set "AAA BBB=value"
    set ""AAA BBB"="
    set "AAA="
    for %%a in ("AAA BBB") do if defined %%~a echo FOR: This works
    
    setlocal EnableDelayedExpansion
    set "varname=AAA BBB"
    if defined !varname! echo Delayed: This works
    
    if defined %varname% ( echo percent: Never comes here 
    ) ELSE ( echo percent: Never comes here ? )
    
    if defined AAA^ BBB ( echo escape1: Never comes here
    ) ELSE ( echo escape1: fails )
    
    set AAA=Hello
    if defined AAA^ BBB ( 
       echo escape2: It only test for AAA the BBB will be "removed"
    ) ELSE ( echo escape2: fails )
    
    set "space= "
    if defined AAA!space!BBB echo inject space: This works
    
    if defined "AAA BBB"  (echo Quote1: Never comes here 
    ) ELSE ( echo Quote1: Fails )
    
    set ""AAA BBB"=value"
    if defined "AAA BBB" echo Quote2: This works, it checks for "AAA BBB" with quotes
    

    In my opionion, in the escape2 example the parser first split the line into tokens this way:
    <if> <defined> <AAA BBB> <echo .... But at the execution time of the if defined it rescan the <AAA BBB> token so it only gets the AAA.
    You can't inject a second escape like AAA^^^ BBB as this only searches for the variable named AAA^

    I can't see a solution without delaying/FOR, as the escaping of the space always fails.

    EDIT: It can also be solved with SET <varname>
    The solution of ijprest uses the SET command to test the variable without the need of escaping the varname.
    But it also shows interessting behaviour with spaces inside and at the end of a varname.

    It seems to follow these rules:
    SET varname searches for all variables beginning with varname, but first it removes all characters after the last space character of varname, and it removes all leading spaces.
    So you can't search for variables with beginning with space (but it is also a bit tricky to create such a varname).

    The same behaviour is also active if the variablename is enclosed into quotes, but then exists one more rule.
    First remove all characters after the last quote, if there are at least two quotes. Use the text inside of the quotes, and use the "space"-rule.

    Sample.

    set    "   abc def ghi"  junk junk
    *** 1. removes the junk 
    set    "   abc def ghi"
    *** 2. removes the quotes
    set       abc def ghi
    *** 3. removes all after the last space, and the trailing spaces
    set abc def
    *** Search all variables beginning with abc def
    
    0 讨论(0)
  • 2021-01-05 12:23

    I also love this sort of question! :)

    Here's another possible solution I came up with... using SET itself to test the existence, and using the ERRORLEVEL result:

    set "A B=foo"
    set A B >nul 2>nul&& echo 1. This works
    set "A B ">nul 2>nul&& echo 2. This works
    
    set "A weird & "complex" variable=foo"
    set A weird ^& "complex" variable >nul 2>nul&& echo 3. This works
    set "A weird & "complex" variable ">nul 2>nul&& echo 4. This works
    

    Note that this only works if your variables are unique in the sense that no variable name is the prefix of another one. Otherwise you risk false positives, as SET's default behavior is to show all variables that start with the parameter you pass. If this could be the case, you could filter the results with findstr:

    set "A B="
    set "A B C=foo"
    set "A B ">nul 2>nul&& echo 5. Failed (false positive)
    set "A B "|findstr /B /L /C:"A B=" >nul||echo 6. This works (no false positive)
    

    Also, the single trailing space after the variable name seems to be required. Without it, SET often mis-parses the input. Bizarrely, if you add an extra space between the "2>nul" and "&&" in case #3 it stops working (unless you remove the space before ">nul")... weird.

    0 讨论(0)
提交回复
热议问题