什么语法将检查是否定义了包含空格的变量名称?

dbe*_*ham 6 windows batch-file environment-variables

Windows用户定义的环境变量名称可以包含除外的任何字符=.

逃避它们可以包含特殊字符.一种更简单的方法是简单地将整个SET表达式括在引号内.例如:

set "A weird & "complex" variable=My value"
set A weird ^& "complex" variable=My value
Run Code Online (Sandbox Code Playgroud)

上面的两个表达式给出了相同的结果 变量名是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
Run Code Online (Sandbox Code Playgroud)

以上逃脱的测试工作得很好.引用的测试不起作用

但是,我如何测试是否存在包含空格的变量?

set "A B=value"
if defined A^ B echo this does not work!
Run Code Online (Sandbox Code Playgroud)

看起来上面应该可行,但事实并非如此!

我正在寻找一个不涉及使用%AB%或!AB来扩展变量的答案!

jeb*_*jeb 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
Run Code Online (Sandbox Code Playgroud)

在我的opionion中,在escape2示例中,解析器首先将行拆分为令牌:
<if> <defined> <AAA BBB> <echo .... 但是在if定义的执行时,它会重新扫描<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
Run Code Online (Sandbox Code Playgroud)