gpt4 book ai didi

string - Windows批处理文件中的IF条件下的“…”和x“…”之间有什么区别?

转载 作者:行者123 更新时间:2023-12-02 03:19:57 27 4
gpt4 key购买 nike

我最近找到了Find if substring is in string (not in a file)帖子,其中指出

@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%""%string%"有什么区别?

最佳答案

那简直是一个非常糟糕的编码字符串比较。两侧的x都可以比较两个字符串,即使Windows命令处理器在执行命令IF之前用空字符串解析整个命令行时也用Windows命令处理器替换了%str1:bcd=%%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分配给环境变量 str1

IF条件会将环境变量 str1的值与所有出现的 bcd值与未修改的变量值进行比较。即使在包含空格或“&”符号或重定向运算符 <>|的情况下,两个字符串周围的双引号也可以比较两个字符串。命令IF在比较两个字符串时包括双引号。

那么这段代码现在安全吗?

不,不是有人用 test_bcd"作为缺少第一双引号的参数字符串将批处理文件称为无效的情况。在这种情况下,由 cmd.exe执行的第一个IF命令行为:

if "test_bcd"" == "" goto EndBatch


错误的指定参数字符串的尾随 "不会被 cmd.exe删除,并在执行时在此命令行上导致语法错误,因为可以在命令提示符窗口中运行批处理文件并将第一行修改为 @echo on

一种不使用延迟的环境变量扩展的解决方案是:

@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


该代码确保在执行IF命令比较字符串之前, str1不包含任何双引号。

另一个解决方案是使用延迟的环境变量扩展:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "str1=%~1"
if not "!str1:bcd=!" == "!str1!" echo It contains bcd
endlocal


在不使用延迟的环境变量扩展的情况下,上述代码看起来更好。但是,如果参数字符串是例如 "!Hello!",则它不能按预期方式工作,因为在这种情况下, if not条件也成立,因此输出是消息 It contains bcd,尽管字符串 !Hello!不包含

解决方案是:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "str1=%~1"
setlocal EnableDelayedExpansion
if not "!str1:bcd=!" == "!str1!" echo It contains bcd
endlocal
endlocal


在将参数字符串分配给环境变量 bcd时未启用延迟扩展,这导致将字符串 str1中的感叹号解释为文字字符。然后使用延迟的环境变量扩展来启用延迟扩展以进行字符串比较,从而避免在执行IF命令之前使用 "!Hello!"修改命令行本身。

为了了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。


cmd.exe ...解释 call /?,不如此处完成。
%~1
echo /?
endlocal /?
goto /?
if /?
set /?


也可以看看:


How does the Windows Command Interpreter (CMD.EXE) parse scripts? ...一个很长的答案,每个批处理文件编写者都应从上至下仔细阅读。
forfiles - FALSE vs. false (doesn't work with lower case?) ...这个答案是关于命令IF的参数处理的。
Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files ...此答案详细说明了命令IF如何完成字符串比较。
Why is no string output with 'echo %var%' after using 'set var = text' on command line? ...此答案说明了为什么应普遍使用 setlocal /?而不是其他变体。
Single line with multiple commands using Windows batch file ...说明了双引号参数字符串之外的 set "variable=value"&如何由 ||解释。
Microsoft关于 Using command redirection operators的文章介绍了 cmd.exe如何解释双引号参数字符串之外的 <>|&

关于string - Windows批处理文件中的IF条件下的“…”和x“…”之间有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52414721/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com