问题描述
这里是示例:
set /a "number1=1"
set /a "number2=10"
if %number1% LSS %number2% (set /a "number1=%number1%+1")
echo result=%number1%
result=2
set /a "number1=%number1%+(%number1% LSS %number2%)"
?
Unbalanced parenthesis.
result=1
解决方法
set /A
command没有比较运算符。
但是,如果第一个数字小于第二个数字,则有一种方法可以比较两个数字并获得-1
的值。为此,我们需要知道逻辑右移运算符>>
实际上执行算术移位,这意味着代表符号的最高有效位的值向左移,因此当前保持数字的符号。
例如:
- 向右移动一位的数字
+10
(二进制表示00000000 00000000 00000000 00001010
)变为+5
(二进制表示00000000 00000000 00000000 00000101
); - 向右移动一位的数字
-10
(二进制表示11111111 11111111 11111111 11110110
)变为-5
(二进制表示11111111 11111111 11111111 11111011
);
当我们向右移动31个(或更多)位位置时,结果是符号位的32倍(因为我们有32位带符号的整数),结果是-1
的值为负输入值,0
输入其他值。
当我们现在应用此技术时,它将导致我们找到以下代码:
set /A "number1=%number1%-((%number1%-%number2%)>>31)"
由于%
会将任何不代表数字或运算符的字符串解释为变量名,因此您可以省略周围的set /A
符号:
set /A "number1=number1-((number1-number2)>>31)"
这可以使用适当的赋值运算符进一步简化:
set /A "number1-=(number1-number2)>>31"
,
因此,您在寻找函数或宏之类的东西时可以将值传递给评估吗?
下面是一个宏,演示了该概念。这不是一个完整的解决方案,因为应该对字符串进行填充,使它们在评估之前具有相等的长度
@Echo Off
Set "Compare=Set "$RV="&For %%n in (1 2)Do if %%n==2 (For /F "Tokens=1,2 Delims={}" %%G in ("!Strings!")Do ((If "%%~G" LSS "%%~H" (Set "$RV=LSS") Else If "%%~G" EQU "%%~H" (Set "$RV=EQU") Else If "%%~G" GTR "%%~H" (Set "$RV=GTR"))&Echo/%%~G !$RV! %%~H))Else Set Strings="
Setlocal EnableDelayedExpansion
rem // example usage
%Compare:$RV=Ex[1]%{one}{oneb}
%Compare:$RV=Ex[2]%{one}{one}
%Compare:$RV=Ex[3]%{oneb}{one}
%Compare:$RV=Ex[4]%{13}{02}
%Compare:$RV=Ex[5]%{02}{13}
Echo/rem // Integers need to be 0 prefixed and strings should be padded to equal length or will return false:
%Compare:$RV=Ex[6]%{2}{13}
%Compare:$RV=Ex[7]%{two}{oneplus}
Set Ex[
下面是完全实现的比较宏,可填充字符串以防止在字符串长度不同时产生错误的结果。为了便于阅读,使用\n
换行语法定义了该宏,但是还包括了复合版本。
@Echo Off & Setlocal DISABLEdelayedexpansion
rem // Pads string with 125 characters to prevent false results when string lengths differ. If comparing strings exceeding 125 characters in length,rem // increase length of the padding and adjust s1 and s2 Substring modification length to match the number of padding characters.
Set "PAD=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
(Set \n=^^^
%= Newline Variable. Do not Modify. =%
)
Set Compare=Set "$RV=" ^& For %%n in (1 2)Do if %%n==2 (%\n%
For /F "Tokens=1,2 Delims={}" %%G in ("!Strings!")Do (%\n%
Set "s1=!PAD!%%~G" ^& Set "s1=!s1:~-125!" ^& Set "s2=!PAD!%%~H" ^& Set "s2=!s2:~-125!"%\n%
If "!s1!" LSS "!s2!" (Set "$RV=LSS")%\n%
If "!s1!" EQU "!s2!" (Set "$RV=EQU")%\n%
If "!s1!" GTR "!s2!" (Set "$RV=GTR")%\n%
Echo/%%~G !$RV! %%~H%\n%
)%\n%
)Else Set Strings=
Setlocal ENABLEdelayedexpansion
rem // example usages
For %%A in (one two three)Do for %%B in (three two one)Do %Compare:$RV=Ex[0]%{%%A}{%%B}
%Compare:$RV=Ex[1]%{one}{oneb}
%Compare:$RV=Ex[2]%{one}{one}
%Compare:$RV=Ex[3]%{oneb}{one}
%Compare:$RV=Ex[4]%{13}{2}
%Compare:$RV=Ex[5]%{2}{13}
Set Ex[
Endlocal & Endlocal & Goto :Eof
rem // compound version of Compare Macro:
Set "Compare=Set "$RV="&For %%n in (1 2)Do if %%n==2 (For /F "Tokens=1,2 Delims={}" %%G in ("!Strings!")Do (Set "s1=!PAD!%%~G"&Set "s2=!PAD!%%~H"&Set "s1=!s1:~-125!"&Set "s2=!s2:~-125!"&(If "!s1!" LSS "!s2!" (Set "$RV=LSS") Else If "!s1!" EQU "!s2!" (Set "$RV=EQU") Else If "!s1!" GTR "!s2!" (Set "$RV=GTR"))&Echo/%%~G !$RV! %%~H&Set "s1="&Set "s2=")) Else Set Strings="
- 比较宏区分大小写。如果您需要忽略大小写,请更改宏中的
If
条件以包括/I
开关
要在所需上下文中使用宏,请执行以下操作:
(%compare%{String 1}{String 2}) > Nul & If "!$RV!"=="LSS" (Echo/true)& Rem // replace Echo command within Parantheses with desired command
- 字符串1和2代表您要比较的任何变量或For循环令牌。