我想代表多个条件,例如:
if [ ( $g -eq 1 -a "$c" = "123" ) -o ( $g -eq 2 -a "$c" = "456" ) ]
then
echo abc;
else
echo efg;
fi
但是当我执行脚本时,它显示
syntax error at line 15: `[' unexpected,
第15行显示的是....
这种情况怎么了?我猜这是有问题的()
。
我想代表多个条件,例如:
if [ ( $g -eq 1 -a "$c" = "123" ) -o ( $g -eq 2 -a "$c" = "456" ) ]
then
echo abc;
else
echo efg;
fi
但是当我执行脚本时,它显示
syntax error at line 15: `[' unexpected,
第15行显示的是....
这种情况怎么了?我猜这是有问题的()
。
Answers:
经典技术(转义元字符):
if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi
我已经$g
用双引号将引用括起来;通常,这是一个好习惯。严格来说,并不需要括号,因为的优先级-a
和-o
使得它纠正,甚至没有他们。
请注意,-a
and -o
运算符是test
aka 的POSIX规范的一部分[
,主要是为了向后兼容(例如,因为它们是test
7th Edition UNIX 的一部分),但是POSIX将它们明确标记为“过时”。Bash(请参阅条件表达式)似乎抢先了经典和POSIX的含义,-a
并-o
带有自己的接受参数的替代运算符。
一定要小心,您可以使用更现代的[[
运算符,但请注意,例如Bash和Korn Shell中的版本不必相同。
for g in 1 2 3
do
for c in 123 456 789
do
if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
then echo "g = $g; c = $c; true"
else echo "g = $g; c = $c; false"
fi
done
done
在Mac OS X上使用Bash 3.2.57运行示例:
g = 1; c = 123; true
g = 1; c = 456; false
g = 1; c = 789; false
g = 2; c = 123; false
g = 2; c = 456; true
g = 2; c = 789; false
g = 3; c = 123; false
g = 3; c = 456; false
g = 3; c = 789; false
您不需要像使用变量[[
一样用引号引起来,[
因为它不是以与[
。
这不是一个经典的问题吗?
我会这么想的。但是,还有另一种选择,即:
if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi
的确,如果您阅读了该autoconf
工具或相关软件包的“便携式外壳”指南,则建议使用“ ||
”和“ &&
” 这种符号。我想您甚至可以做到:
if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi
在动作像回声一样微不足道的地方,这还不错。当要重复的动作块为多行时,重复会很痛苦,并且较早的版本之一是可取的-否则您需要将动作包装到在不同then
块中调用的函数中。
-a
实际上的优先级高于-o
(不像&&
和||
在外壳-然而,内部 bash
[[ ... ]]
条件句,&&
也有优先级高于||
)。如果您想要避免这种情况-a
并-o
获得最大的鲁棒性和可移植性(这是POSIX手册页本身所建议的),则也可以使用子shell进行分组:if ([ $g -eq 1 ] && [ "$c" = "123" ]) || ([ $g -eq 2 ] && [ "$c" = "456" ])
if test "$g" -eq 1 -a "$c" = "123" || test "$g" -eq 2 -a "$c" = "456"; then ...
&&
或||
也更可取,因为它的行为更像其他语言中的条件语句,并允许您短路条件。例如:if [ -n "${check_inodes}" ] && [ "$(stat -f %i "/foo/bar")" = "$(stat -f %i "/foo/baz")" ]
。这样,如果check_inodes
为空,则避免两次调用stat
,而较大,复杂的测试条件必须在执行之前处理所有参数(如果忘记了这种行为,也可能导致错误)。
在Bash中:
if [[ ( $g == 1 && $c == 123 ) || ( $g == 2 && $c == 456 ) ]]
bash
。顺便说一句:在这种特殊情况下,甚至不需要括号,因为内部 [[ ... ]]
条件条件 &&
实际上比||
-不同于外部条件条件具有更高的优先级。
if
/ else
语句,并在它们之间添加代码then
并fi
放入函数中,以免重复。在非常简单的情况下,您可以使用case
带有;&
fallthrough 的语句(在Bash 4中)。
如果字符串变量中有空格并检查是否存在,请小心。确保正确引用它们。
if [ ! "${somepath}" ] || [ ! "${otherstring}" ] || [ ! "${barstring}" ] ; then
在bash中进行字符串比较时,可以使用以下技术。
if [ $var OP "val" ]; then
echo "statements"
fi
例:
var="something"
if [ $var != "otherthing" ] && [ $var != "everything" ] && [ $var != "allthings" ]; then
echo "this will be printed"
else
echo "this will not be printed"
fi
#!/bin/bash
current_usage=$( df -h | grep 'gfsvg-gfslv' | awk {'print $5'} )
echo $current_usage
critical_usage=6%
warning_usage=3%
if [[ ${current_usage%?} -lt ${warning_usage%?} ]]; then
echo OK current usage is $current_usage
elif [[ ${current_usage%?} -ge ${warning_usage%?} ]] && [[ ${current_usage%?} -lt ${critical_usage%?} ]]; then
echo Warning $current_usage
else
echo Critical $current_usage
fi
您也可以链接两个以上的条件:
if [ \( "$1" = '--usage' \) -o \( "$1" = '' \) -o \( "$1" = '--help' \) ]
then
printf "\033[2J";printf "\033[0;0H"
cat << EOF_PRINT_USAGE
$0 - Purpose: upsert qto http json data to postgres db
USAGE EXAMPLE:
$0 -a foo -a bar
EOF_PRINT_USAGE
exit 1
fi
test
([
)而不是shell 求值的。Shell仅评估的退出状态[
。