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

发布于 2024-12-17 19:11:30 字数 756 浏览 0 评论 0原文

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

可以通过转义特殊字符来包含它们。一种更简单的方法是简单地将整个 SET 表达式括在引号内。例如:

set "A weird & "complex" variable=My value"
set A weird ^& "complex" variable=My value

上面的两个表达式给出相同的结果。变量名称是一个奇怪的& “complex”变量,值为我的值

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!

看起来上面的方法应该有效,但事实并非如此!

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

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

Special characters can be included by escaping them. A simpler method is to simply enclose the entire SET expression within quotes. For example:

set "A weird & "complex" variable=My value"
set A weird ^& "complex" variable=My value

Both expressions above give the same result. The variable name is A weird & "complex" variable and the value is My value

The IF DEFINED construct is used to test if a variable is defined. Quotes don't work for this test, special characters in the name (including quotes) must be escaped.

set "A&B=value"
if defined A^&B echo This works
if defined "A&B" echo This does not work

The above escaped test works just fine. The quoted test does not work

But how can I test if a variable containing spaces exists?

set "A B=value"
if defined A^ B echo this does not work!

It seems like the above should work, but it doesn't!

I'm looking for an answer that does NOT involve expanding the variable using %A B% or !A B!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

云巢 2024-12-24 19:11:30

有趣的问题(我喜欢这个语法基础问题)。

显然,您知道如何通过延迟扩展来检查它,并且 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
您不能注入像 AAA^^^ BBB 这样的第二个转义符,因为它只搜索名为 AAA^ 的变量,

如果不延迟/FOR,我看不到解决方案,因为逃离空间总是失败。

编辑:也可以用 SET
解决
ijprest的解决方案是使用SET命令来测试变量,而不需要对varname进行转义。
但它也显示了变量名称内部和末尾的空格的有趣行为。

它似乎遵循以下规则:
SET varname 搜索以 varname 开头的所有变量,但首先删除 varname 最后一个空格字符之后的所有字符,并删除所有前导空格。
所以你不能搜索以空格开头的变量(但创建这样的变量名也有点棘手)。

如果变量名括在引号中,则同样的行为也处于活动状态,但随后又存在一条规则。
如果至少有两个引号,请首先删除最后一个引号之后的所有字符。
使用引号内的文本,并使用“空格”规则。

样本。

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

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
天邊彩虹 2024-12-24 19:11:30

我也喜欢问这种问题! :)

这是我想出的另一个可能的解决方案...使用 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

请注意,只有当您的变量是唯一的(即没有变量)时,这才有效name 是另一个的前缀。否则,您将面临误报的风险,因为 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>nul”和“&&”之间添加额外的空格如果#3它停止工作(除非你删除“>nul”之前的空格)......很奇怪。

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.

人心善变 2024-12-24 19:11:30

另一种方法是将其重新分配给另一个变量(没有空格的变量)并测试。参见这里:

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
)

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
)
风轻花落早 2024-12-24 19:11:30

如果需要的话,我通过将标志定义为 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=

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=
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文