在 bash 手册中,第 6.5 节 Shell 算术说
<= >= < > comparison
== != equality and inequality
&& logical AND
|| logical OR
它们的含义似乎暗示它们用于条件表达式。但它们出现在算术表达式部分。
那么它们可以用在条件表达式?
<=,>=,<,>,==,!=
在 6.4 节中,我们已经有了条件表达式的运算符,它们与算术表达式类似:arg1 操作 arg2
OP 是“-eq”、“-ne”、“-lt”、“-le”、“-gt”或“-ge”之一。如果 arg1 分别等于、不等于、小于、小于或等于、大于或大于或等于 arg2,这些算术二元运算符将返回 true。 Arg1和arg2可以是正整数或负整数。
我们还已经有了条件表达式的运算符,它们类似于算术表达式的
&&
和:||
-a
对于-o
即test
[...]
&&
并||
为[[...]]
.
既然我们已经为条件表达式引入了运算符,为什么我们还需要为算术表达式引入类似的运算符呢?
它们可以用于测试命令?
我们知道
if
后面是一个测试命令if 命令的语法为:
if test-commands; then consequent-commands; [elif more-test-commands; then more-consequents;] [else alternate-consequents;] fi
[...]
两者[[...]]
都采用条件表达式并创建测试命令。他们可以采用算术表达式吗?让我更加困惑的是,当它们中的算术
[...]
表达式[[...]]
用作测试命令时,[...]
行为不正确,而[[...]]
正确:$ if [ 1 > 2 ]; then echo h; else echo b; fi h $ if [ 1 < 2 ]; then echo h; else echo b; fi h $ if [[ 1 < 2 ]]; then echo h; else echo b; fi h $ if [[ 1 > 2 ]]; then echo h; else echo b; fi b
答案1
这很简单。你只需要理解[]
,[[]]
并且(())
作为完全不同的野兽。
[ expression ]
只是程序的调用[
(只是 的名称不同test
),并将表达式作为参数,就像 bash 中的所有命令调用一样。这意味着,您必须在参数之间使用空格,尤其是 after[
和 before ]
,并且关键字和特殊字符必须转义或引用,并且变量以通常的方式扩展。
在表达式中,-gt, -lt
和 related 用于数值比较,而>, <
和 sort 用于字符串比较。可以认为[
与 bash 无关,只是调用一个计算表达式并返回 0(真)或非零(假)的命令,就像所有程序一样。
布尔运算符&&
和||
不能在那里使用,因为它们由 bash 解释,而不是test
作为参数传递。-a
并被-o
用来代替。但您始终可以执行[ test1 ] && [ test2 ] || [ test3 ]
,这是 3 个测试调用,由 的bash
常用布尔运算符组合而成(也就是说,如果第一个失败,则跳过第二个)。
请注意,bash
仍然带有它自己的[
(builtin) 实现,但这并没有改变它的语法处理方式。
[[ ]]
和(( ))
不是命令的内置替代品,而是特殊语法的一部分,因此适用不同的规则。有关如何处理变量名通配符的详细信息,请参阅手册页。布尔运算符&&
和||
具有通常的含义。
一种[[ ]]
是以字符串为中心的:所有比较都是针对字符串的(但比 中更“现代”、更了解语言环境[
,尽管test
可能与平台相关)。它还处理文件测试、正则表达式等。
用于(( ))
算术表达式。变量名称不需要$
在那里,并且您通常可以在其中编写数学表达式 - 当然包括比较(数字)。这种情况下的比较与任何其他算术表达式没有什么不同,true 为 1,false 为 0,并且您可以编写类似(( x=y*(z>4) ))
.如果在条件表达式中使用,非零为真,零为假。您还可以将结果捕获为$(( ))
.
所以:
[[ ]]
字符串条件、模式匹配和文件测试(( ))
算术表达式和条件[ ]
测试命令:处理布尔运算符和比较运算符的特殊非标准语法
答案2
“条件表达式”是test
[
or[[
命令内部使用的内容。
所以,你的问题1和2的意思是一样的:
- 它们可以用在条件表达式中吗?:可以。
- 它们可以在测试命令中使用吗?:是的。
然而,它们并不意味着你的想法:
$ if [[ 1 < 2 ]]; then echo yes; else echo no; fi
yes
$ if [[ 10 < 2 ]]; then echo yes; else echo no; fi
yes
$ if [[ e < è ]]; then echo yes; else echo no; fi
yes
正如手册所述,这种比较:
True if string1 sorts before string2 lexicographically.
即:按字典顺序(并受 LC_COLLATE 变量的影响)
简单的测试[
会将输出重定向到文件:
$ if [ e < è ]; then echo h; else echo b; fi
bash: è: No such file or directory
b
要使其正常工作,您需要使用反斜杠(引用 < 和 >):
$ if [ e \< è ]; then echo h; else echo b; fi
h
但我不建议在 中使用 < test
。
在其他可能使用 <、<=、>、>= 的地方是算术测试内部,这可能是 if 测试的一部分:
$ if (( 12 <= 15 )); then echo "yes"; fi
yes
是的,这相当于:
$ if [[ 12 -le 15 ]]; then echo "yes"; fi
yes
并且非常类似于:
$ if [ 12 -le 15 ]; then echo "yes"; fi
yes
所以,是的,这一切:
<= >= < > comparison
== != equality and inequality
&& logical AND
|| logical OR
用于算术表达式中的条件表达式:
$ if (( ( ((2<3)&&(3>7)) * 18 ) == 0 )); then echo "yes"; fi
yes
这与命令中的条件表达式不同test
。