批处理中“ ...”和x“ ...”之间的区别

时间:2018-09-19 21:56:50

标签: string batch-file

我最近在这篇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的实际效果的任何解释。那么xx"%string%"有什么区别?

(链接到实际文档是一个有效的答案,因为我找不到任何答案。)

2 个答案:

答案 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 /?

另请参阅: