我最近在这篇https://stackoverflow.com/a/7006016/4374266帖子中发现,有人在考虑考虑
headers
然后
等号两边之前的
@setlocal enableextensions enabledelayedexpansion @echo off set str1=%1 if not x%str1:bcd=%==x%str1% echo It contains bcd endlocal
是为了确保字符串x
可以正常工作。它还可以防止某些“不合适的”起始字符。
但是我还没有找到关于此bcd
的实际效果的任何解释。那么x
和x"%string%"
有什么区别?
(链接到实际文档是一个有效的答案,因为我找不到任何答案。)
答案 0 :(得分:3)
在字符串前面加上x
(或任何其他字母字符)可确保即使在字符串为空的情况下,关系语句在语法上也有效。
假设str1
是一个空字符串。然后,替换后的比较%str1:bcd=%==%str1%
退化为==
,在语法上是无效的。
但是,前面有x
时,比较将变为x==x
并且可以进行评估。自然地,向两个字符串中的每个字符串添加相同的前缀不会影响它们的(不相等)。
答案 1 :(得分:3)
这只是一个非常糟糕的编码字符串比较。即使x
或%str1:bcd=%
被Windows命令处理器在执行命令< strong> IF 。
但是,由于在环境变量%str1%
的值包含空格字符或cmd.exe
的情况下出现语法错误,因此str1
会立即退出批处理文件执行。
将参数字符串括在双引号中会导致获得除百分号以外的所有字符,并且启用了延迟的环境变量扩展,还会将感叹号解释为文字字符,包括在双引号字符串之外的空格,该空格被解释为参数字符串分隔符。 >
更好的是:
"&<>|
首先比较批处理文件的第一个参数,而不用双引号引起来的空字符串。因此,如果启动批处理文件时不带任何参数,或者仅使用@echo off
setlocal EnableExtensions DisableDelayedExpansion
if "%~1" == "" goto EndBatch
set "str1=%~1"
if not "%str1:bcd=%" == "%str1%" echo It contains bcd
:EndBatch
endlocal
作为第一个参数字符串,则Windows命令处理器将执行命令 GOTO ,从而恢复使用命令压入堆栈的先前环境SETLOCAL 并退出批处理文件。
否则,批处理文件实际上使用参数字符串来调用。该参数字符串分配给环境变量""
,并删除周围的双引号(如果有的话)。因此,在使用参数str1
调用批处理文件时,将值test
分配给环境变量test
,并在使用str1
对其进行调用时,将值"another test"
没有双引号被分配给another test
。甚至在使用错误的编码参数字符串str1
(缺少第二个"bcd test
)调用批处理文件时,也仅将"
分配给了环境变量bcd test
。
IF 条件将环境变量str1
的值与所有出现的str1
删除后的值与未修改的变量值进行比较。即使在包含空格或与号或重定向运算符bcd
的情况下,两个字符串周围的双引号也可以比较两个字符串。命令 IF 包含在比较两个字符串时的双引号。
那么这段代码现在安全吗?
否,不是有人用<>|
作为缺少第一双引号的参数字符串将批处理文件称为无效的情况。在这种情况下,test_bcd"
执行的第一个 IF 命令行是:
cmd.exe
if "test_bcd"" == "" goto EndBatch
不会删除错误的指定参数字符串的结尾"
,并且会在执行时在此命令行上引起语法错误,这是从命令中运行批处理文件时可以看到的提示窗口,第一行修改为cmd.exe
。
不使用延迟的环境变量扩展的一种解决方案是:
@echo on
此代码可确保在执行 IF 命令比较字符串之前,@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "str1=%~1"
if not defined str1 goto EndBatch
set "str1=%str1:"=%"
if not defined str1 goto EndBatch
if not "%str1:bcd=%" == "%str1%" echo It contains bcd
:EndBatch
endlocal
不包含任何双引号。
另一种解决方案是使用延迟的环境变量扩展:
str1
作为上面的代码,在不使用延迟的环境变量扩展的情况下,它看起来更好。但是,如果参数字符串例如是@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "str1=%~1"
if not "!str1:bcd=!" == "!str1!" echo It contains bcd
endlocal
,则它不能按预期方式工作,因为在这种情况下,"!Hello!"
条件也成立,因此尽管字符串{{ 1}}不包含if not
。
解决方案是:
It contains bcd
在将参数字符串分配给环境变量!Hello!
时未启用延迟扩展,这导致将字符串bcd
中的感叹号解释为文字字符。然后启用延迟扩展以使用延迟环境变量扩展进行字符串比较,从而避免在执行 IF 命令之前使用@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "str1=%~1"
setlocal EnableDelayedExpansion
if not "!str1:bcd=!" == "!str1!" echo It contains bcd
endlocal
endlocal
修改命令行本身。
要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。
str1
...解释"!Hello!"
,不如此处所做的好。cmd.exe
call /?
%~1
echo /?
endlocal /?
goto /?
另请参阅:
if /?
应该普遍使用,而不是其他变体。set /?
如何解释双引号参数字符串之外的setlocal /?
和set "variable=value"
。&
如何解释双引号参数字符串之外的||
。