在Windows批处理文件中,NEQ、LSS、GTR等符号的等效表示。

17

在批处理中,当使用if命令时,我总是使用 ==。(例如:if "19"=="3" echo My computer doesnt know maths

那么其他的命令(LSSLEQNEQ等)呢?难道没有像Unix一样的!=表示NEQ吗?

我想要使用符号的原因是因为我听说对于文本或数字,符号比使用文本变量更有效率。

无论如何,我仍然想知道。谢谢。


2
你可以使用 if not str1==str2 ...,但我认为除了 == 之外,没有任何符号比较运算符。如果你考虑一下,最有可能的符号已经用于重定向,所以可能需要一些可怕的引用或其他奇怪的语法才能使用它们。我不知道为什么他们从未支持 != - Michael Burr
3
可能是因为使用延迟扩展时需要使用相同可怕的[转义|引用|奇异语法],所以才这样。 - Stephan
2个回答

36

运算符如 > 之类的在 shell 脚本中不被使用,是因为它们具有特殊含义。 > 被用于重定向输出;< 用于重定向输入,等等。

Microsoft 文档 列出了以下运算符:

Operator | Description
EQU      | equal to
NEQ      | not equal to
LSS      | less than
LEQ      | less than or equal to
GTR      | greater than
GEQ      | greater than or equal to

此外,单词 not 用于否定条件。

我想使用符号的原因是因为有人说使用符号比使用文本变体更有效,无论是对于文本还是数字。

他们可能指的是 bash 及其大型操作符目录。它为整数和字符串操作数提供不同的运算符。


22
Windows命令处理器的内部命令IF默认只有两个运算符:
  1. ==,用于对两个参数进行字符串比较,判断它们是否相等,即使用lstrcmpW函数,当lstrcmpW返回0时条件为true
  2. not==结合使用,用于反转字符串比较结果的相等性,即当两个比较的字符串不相等时条件为true
因此,命令行为:
if "19"=="3" echo My computer doesn't know maths

使用字符串"19""3"运行lstrcmpW函数,这意味着比较的字节流是十六进制22 31 39 22 0022 33 22 00。在运行字符串比较之前,双引号不会被移除。引号包含在字符串比较中

命令提示符窗口中运行命令if /?,可以输出IF命令的帮助信息。该帮助文件解释了所有选项和附加操作符,这些选项和操作符在默认情况下启用了命令扩展功能。

有一个选项/I,可以通过使用lstrcmpiW函数而不是lstrcmpW函数来进行大小写不敏感的比较。

示例:

if /I not "%~1" == "/I" echo First argument is neither /i nor /I.

有附加的比较运算符EQUNEQLSSLEQGTRGEQ,启用命令扩展。

在Windows命令行中,尖括号<>作为redirection operators使用。因此,它们不能用作IF条件的比较运算符。感叹号!也不可用作运算符,因为在启用延迟变量扩展时它表示变量引用的开头/结尾。运行set /?setlocal /?endlocal /?了解有关延迟变量扩展用法的详细信息。

Windows命令解释器尝试使用wcstol将两个参数字符串都转换为带符号的32位整数,使用base 0(自动检测基数)在使用EQUNEQLSSLEQGTRGEQ时。如果对于两个参数字符串都成功进行了整数比较,那么就会执行比较操作,因为这两个比较的字符串是...
  • 十进制数,第一个字符可以选择为-+,其余字符都是十进制数字0123456789,第一个数字不能为0,例如-2147483648-200+10322147483647
  • 十六进制数,第一个字符可以选择为-+,接下来是0x0X,其余字符都是十六进制数字0123456789ABCDEFabcdef,例如-0x80000000-0XC8+0x0a0x200x7fffFFFF
  • 八进制数,第一个字符可以选择为-+,接下来是0,其余字符都是八进制数字01234567,例如-020000000000-0310+012040017777777777
否则,两个参数字符串将再次使用lstrcmpWlstrcmpiW进行比较,还可以使用附加的/I与运算符EQUNEQLSSLEQGTRGEQ,并且比较运算符应用于字符串比较函数的整数结果。
注意:0809以及其他被人们解释为具有一个或多个前导0且包含89的十进制数被解释为无效的八进制数,因此导致产生字符串而不是整数比较。
将两个字符串参数转换为带符号的32位整数需要一些额外的处理器指令(取决于CPU性能,大约几纳秒或微秒)。因此,整数比较略慢一些,但通常不会真正明显感觉到较慢。
示例:
if 014 EQU 12 echo Octal number 014 is equal decimal number 12.
if 0x0C EQU 12 echo Hexadecimal number 0C is equal decimal number 12.
if /I 0X0C EQU 014 Hexadecimal number 0C is equal octal number 014.

选项/I在使用除==以外的比较运算符时被忽略,只要两个字符串都可以成功转换为32位有符号整数即可。这由上面的第三行证明了。只有在使用EQUNEQLSSLEQGTRGEQ运算符时,当其中一个字符串无法成功转换为整数时,才会考虑/I选项,如下例所示:
if /I "0X20" EQU "0x20" echo String "0X20" is case-insensitive equal string "0x20".

如果在使用EQU、NEQ、LSS、LEQ、GTR、GEQ中的一个时,两个参数中的一个用双引号括起来,或者两个字符串中有一个不是表示有效整数的字符串,比较将始终使用lstrcmpW或lstrcmpiW(取决于是否使用/I选项)。lstrcmpW和lstrcmpiW都返回一个整数作为结果,该结果可以是负数、零或正数。根据所使用的运算符,将此整数结果与整数值0进行比较。
示例:
if 010 NEQ "10" echo String 010 is not equal string "10".
if "100" LSS "20" echo String "100" is less than string "20".

在第二个例子中,左侧的第二个字符1具有较低的代码值(49 = 0x31),而右侧的第二个字符2具有较高的代码值(50 = 0x32),这导致lstrcmpW返回一个负值,从而使得function result LSS 0为真。
请注意,Windows环境变量始终是字符串类型,并且在使用整数比较或整数运算时需要将其转换为整数。
在大多数情况下,建议使用string1 == string2not string1 == string2来比较两个不表示整数值的字符串,而不是使用string1 EQU string2string1 NEQ string2,直接使用lstrcmpWlstrcmpiW。否则,在使用EQUNEQ比较字符串时,Windows命令处理器会先使用wcstol,这会浪费几纳秒或几微秒的时间,因为wcstol无法将要比较的两个字符串之一转换为整数,然后cmd.exe会运行lstrcmpWlstrcmpiW,就像立即使用字符串比较运算符==一样。
还有一个重要的事实:

在使用比较运算符EQUNEQLSSLEQGTRGEQ时,如果其中一个参数包含无效字符,则cmd.exe在执行IF条件时会将其视为字符串而不是整数进行比较。然而,当其中一个参数小于-2147483648或大于2147483647等超出范围的情况时,仍会进行整数比较,详见weird results with IF

通过将两个值作为字符串进行比较,可以绕过值范围限制,确保两个值字符串具有相同数量的字符。以下是一个示例,用于判断文件是否具有两个或更多的GiB(即文件大小为2147483648字节或更多)。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if "%~1" == "" ( set "FileName=%~f0" ) else set "FileName=%~1"
for %%I in ("%FileName%") do set "FileSize=000000000000000%%~zI"
if "%FileSize:~-16%" GEQ "0000002147483648" (
    echo "%FileName%" is greater or equal 2 GiB.
) else echo "%FileName%" is less than 2 GiB.
endlocal
pause

将传递给批处理文件的文件的文件大小分配给环境变量FileSize,作为字符串,并始终在开头至少有15个额外的零位。
然后将FileSize字符串与表示2 GiB字节的字符串0000002147483648的最后16位进行比较。 lstrcmpW按字节比较两个等长的字符串,其中每个字符串中的每个字节都只能具有十六进制值0x30到0x39。如果左侧字符串的当前字节小于右侧字符串的当前字节,则lstrcmpW立即返回负值,这意味着文件大小小于2 GiB。如果左侧字符串的当前字节大于右侧字符串的当前字节,则lstrcmpW立即返回正值,这意味着文件大小大于2 GiB。如果两个字符串完全相同,则lstrcmpW返回零,这意味着文件大小恰好为2 GiB。
请注意,使用字符串比较来比较值需要确保两个值具有相同数量的字符,以获得准确的结果。具有较少数字的值字符串必须在前面添加正确数量的0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接