Bash if语句中包含算术、比较和正则运算符的多个条件
我试图编写一个脚本,读取三个整数,然后检查其中任何两个数的和是否大于第三个数。如果这是真的,那么它会检查这些数字是否相等,并打印一条消息。如果不是,它将检查任意两个数字是否相等,并打印另一条消息。如果以上所有内容均为假,则会打印一条消息,说明所有数字都不同。 我已尝试将其放在以下嵌套条件中:Bash if语句中包含算术、比较和正则运算符的多个条件,bash,shell,if-statement,scripting,Bash,Shell,If Statement,Scripting,我试图编写一个脚本,读取三个整数,然后检查其中任何两个数的和是否大于第三个数。如果这是真的,那么它会检查这些数字是否相等,并打印一条消息。如果不是,它将检查任意两个数字是否相等,并打印另一条消息。如果以上所有内容均为假,则会打印一条消息,说明所有数字都不同。 我已尝试将其放在以下嵌套条件中: read X read Y read Z if [ $X + $Y > $Z ] && [ $X + $Z > $Y ] && [ $Y + $Z > $X
read X
read Y
read Z
if [ $X + $Y > $Z ] && [ $X + $Z > $Y ] && [ $Y + $Z > $X ]
then
if [ $X = $Y = $Z ]
then
echo "All numbers are equal."
elif [ [ $X = $Y ] && [ $X != $Z ] ] || [ [ $X = $Z ] && [ $X != $Y ] ] || [ [ $Z = $Y ] && [ $X != $Y ] ]
then
echo "Two of the numbers are equal."
else
echo "None of the numbers is equal to another."
fi
fi
我已经尝试了所有类型的括号和括号的组合(上面只是其中之一),但到目前为止没有一种有效。
我已经看了相关帖子:
但我还没有发现任何包含算术运算符的覆盖条件。
有人能告诉我什么是正确的方法吗
(编辑:我忘了在原来的帖子中提到我是bash新手,所以请原谅我可能犯的任何严重错误。我仍在试图弄清楚事情是如何运作的。)以下是伊尼安答案的一个变体,它利用了不需要
$
扩展变量的算术运算,它们接受逻辑运算符,并且第一个测试所有数字是否相等的事实允许简化下面的测试
请注意,检查读取的值是否为整数是避免意外行为的好方法
#!/bin/bash
read X
read Y
read Z
if
(( X+Y>Z || X+Z>Y || Y+Z>X ))
then
if
(( X==Y && Y==Z ))
then
echo "All numbers are equal"
elif
(( X==Y || X==Z || Z==Y ))
then
echo "Two of the numbers are equal"
else
echo "All three numbers are different"
fi
fi
算术表达式的$(())将展开为内部表达式的求值结果。如果表达式是一个导致“true”值的测试,或者如果其计算结果为非零值,则for的(())
用作返回0的命令,否则返回非零值。第二种形式对于测试非常有用
另外,我喜欢使用
(())
的属性来处理脚本中的开/关选项。例如,((state_variable))
将在变量为null或0时计算为“false”,否则计算为“true”,这很好地反映了这样一个变量在直觉上的行为方式。以下是Inian答案的一个变体,它利用了不需要$
展开变量的算术运算,它们接受逻辑运算符,并且第一个关于所有数字相等的测试允许简化以下测试
请注意,检查读取的值是否为整数是避免意外行为的好方法
#!/bin/bash
read X
read Y
read Z
if
(( X+Y>Z || X+Z>Y || Y+Z>X ))
then
if
(( X==Y && Y==Z ))
then
echo "All numbers are equal"
elif
(( X==Y || X==Z || Z==Y ))
then
echo "Two of the numbers are equal"
else
echo "All three numbers are different"
fi
fi
算术表达式的$(())将展开为内部表达式的求值结果。如果表达式是一个导致“true”值的测试,或者如果其计算结果为非零值,则for的(())
用作返回0的命令,否则返回非零值。第二种形式对于测试非常有用
另外,我喜欢使用
(())
的属性来处理脚本中的开/关选项。例如,((state_variable))
将在变量为null或0时计算为“false”,否则计算为“true”,这很好地反映了这样一个变量在直觉上的行为方式。您也可以通过增加匹配项和使用case语句来使用不同的方法
应该更容易用更多的变量进行缩放
#!/bin/bash
read X
read Y
read Z
((Matches+=(X==Y)))
((Matches+=(Y==Z)))
((Matches+=(X==Z)))
case "$Matches" in
0) echo "None of the numbers is equal to another.";;
1) echo "Two of the numbers are equal.";;
3) echo "All numbers are equal.";;
esac
您也可以通过增加匹配项并使用case语句来使用不同的方法 应该更容易用更多的变量进行缩放
#!/bin/bash
read X
read Y
read Z
((Matches+=(X==Y)))
((Matches+=(Y==Z)))
((Matches+=(X==Z)))
case "$Matches" in
0) echo "None of the numbers is equal to another.";;
1) echo "Two of the numbers are equal.";;
3) echo "All numbers are equal.";;
esac
一种完全不同的解决问题的方法
#!/bin/bash
declare -A a # declare associative array a
read x; a[$x]=$x
read x; a[$x]=$x
read x; a[$x]=$x
case ${#a[@]} in
1) echo "All numbers are equal." ;;
2) echo "Two of the numbers are equal." ;;
3) echo "None of the numbers is equal to another." ;;
esac
一种完全不同的解决问题的方法
#!/bin/bash
declare -A a # declare associative array a
read x; a[$x]=$x
read x; a[$x]=$x
read x; a[$x]=$x
case ${#a[@]} in
1) echo "All numbers are equal." ;;
2) echo "Two of the numbers are equal." ;;
3) echo "None of the numbers is equal to another." ;;
esac
一个线性函数,浓缩自: 显示所有三种情况:
3a 1 1 1 ; 3a 1 1 2 ; 3a 1 2 3
All numbers are equal.
Two numbers are equal.
No numbers are equal.
一个线性函数,浓缩自: 显示所有三种情况:
3a 1 1 1 ; 3a 1 1 2 ; 3a 1 2 3
All numbers are equal.
Two numbers are equal.
No numbers are equal.
请参阅:
帮助测试
[…]
是测试内置的同义词。您在第一个中意识到,如果只需检查两个大于另一个的数字一次,您不需要检查每个组合。@123是的,您是对的,但我想在某一点之后,我更感兴趣的是找出这样的条件是否可行以及如何实现。请参阅:help test
[…]
是测试内置的同义词。您在第一个中意识到,如果只需检查两个大于另一个的数字一次,您不需要检查每个组合。@123是的,您是对的,但我想在某一点之后,我更感兴趣的是找出这样的条件是否可行以及如何实现。这是OP尝试的一个很好的简化,在我的答案中尝试坚持OP的逻辑,但这看起来很简洁++
你和@Inian都理解我的想法,但你离我最初打算做的有点近。我想我混合了(())
和[[]]
这两种语法。请您再解释一下您在代码后的第一段中描述的内容,(())
的作用是什么?所以,如果我理解正确的话,如果它的计算结果为非零值,则返回0;如果它的计算结果为0,则返回非零数?再次感谢您的帮助。@Ioannis(())
在计算为一个数字时会按照您所说的做,但如果它包含一个测试(即=
,!=
,@Ioannis请注意,(())
可以用于赋值,因此它可能会产生副作用(与[[]]]]
相反)。赋值的形式为((varname=value))
。相等性测试为=
(与[[]]
相反,后者接受=
和=
来测试相等性),因此,如果你不经常使用它,可能会有点混淆。这是OP尝试的一个很好的简化,在我的答案中尝试坚持OP的逻辑,但是