Windows用户定义的环境变量名称可以包含除=
之外的任何字符。
转义它们可以包含特殊字符。一种更简单的方法是简单地将整个SET表达式括在引号内。例如:
set "A weird & "complex" variable=My value"
set A weird ^& "complex" variable=My value
上述两个表达式都给出了相同的结果。变量名称为 A weird & "complex" variable
,值为 My value
IF DEFINED构造用于测试是否定义了变量。引号不适用于此测试,名称中的特殊字符(包括引号)必须转义。
set "A&B=value"
if defined A^&B echo This works
if defined "A&B" echo This does not work
以上转义测试工作正常。引用的测试不起作用
但是如何测试是否存在包含空格的变量?
set "A B=value"
if defined A^ B echo this does not work!
看起来上面应该有效,但事实并非如此!
我正在寻找一个不涉及使用%A B%或!A B来扩展变量的答案!
答案 0 :(得分:5)
有趣的问题(我喜欢这种语法基础问题)。
显然你知道如何通过延迟扩展检查它,并且FOR参数也可以。
@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
在我的选择中,在 escape2 示例中,解析器首先将行拆分为令牌:
<if> <defined> <AAA BBB> <echo ....
但是在的执行时,如果已定义,它会重新扫描<AAA BBB>
令牌,因此它只会获得AAA
。
你不能注入像AAA^^^ BBB
这样的第二个转义,因为它只搜索名为AAA^
的变量
我没有看到没有延迟/ FOR的解决方案,因为空间的逃逸总是失败。
编辑:也可以使用SET <varname>
解决
ijprest的解决方案使用SET命令测试变量,而无需转义varname
但它也显示了在varname内部和末尾有空格的行为。
似乎遵循这些规则:
SET varname
搜索以varname开头的所有变量,但首先删除varname的最后一个空格字符后的所有字符,并删除所有前导空格。
所以你不能用空格开头搜索变量(但是创建这样的varname也有点棘手)。
如果变量名用引号括起来,那么同样的行为也是有效的,但是又存在一个规则 如果至少有两个引号,请首先删除最后一个引号后的所有字符。 使用引号内的文本,并使用“space”-rule。
样品。
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
答案 1 :(得分:3)
我也喜欢这样的问题! :)
这是我提出的另一种可能的解决方案......使用SET本身测试存在,并使用ERRORLEVEL结果:
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
请注意,这仅适用于您的变量 unique ,因为没有变量名称是另一个变量名称的前缀。否则您会冒错误,因为SET的默认行为是显示以您传递的参数开头的所有变量。如果是这种情况,您可以使用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)
此外,似乎需要变量名后面的单个尾随空格。没有它,SET经常错误地解析输入。奇怪的是,如果你在“2&gt; nul”和“&amp;&amp;”之间增加一个额外的空格如果#3它停止工作(除非你删除“&gt; nul”之前的空格)...很奇怪。
答案 2 :(得分:0)
另一种方法是将其重新分配给另一个变量(一个没有空格)并测试 。见这里:
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
)
答案 3 :(得分:-2)
如果需要,我可以通过将标志定义为TRUE来实现......
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=