我目前正在测试脚本中的更改以提高性能。具体来说,我想更改if
为case
语句。
然而,作为 shell 编程的新手,我陷入了这种类型的声明中:
if [ "$A" == "x" -a "$B" == "y" ]
then
let a=a+1
fi
我尝试了这个但没有成功:
case "$A$B" in
"x""y") let a=a+1
;;
esac
我做错了什么?
是否可以在 case 语句中管理“!=”?例如:
if [ "$A" == "x" -a "$B" != "y" ]
then
let a=a+1
fi
答案1
你的case
例子对我有用,但请注意,你正在比较级联和A
,因此如果is和为空B
,则模式也将匹配。 (我认为中间的双引号是多余的。)只需要一个A
xy
B
case
单词与模式进行比较,因此除非通过连接,否则无法比较多个变量。
在标准test
, or[
命令中,比较运算符是=
。==
适用于某些系统,但并非全部。此外,使用组合条件-a
是有问题的,至少对于诸如 之类的条件是这样-n
。 (看这个问题)。更好地使用if [ "$A" = x ] && [ "$B" = y ] ; then ...
。
至于反转 a case
,您需要想出一个匹配除目标字符串之外的所有内容的模式。extglob
在重击中其他允许匹配除以下内容之外的任何内容:
case $B in !(y) ) echo not y ;; esac
如果没有它,您需要做更多的工作来反转模式,或者使用多个模式,第一个模式与字符串匹配,稍后的默认匹配执行实际操作。
case $B in ??*) echo not y ;; [^y]) echo also not y ;; esac
case $B in y) ;; *) echo still not y ;; esac
(没有保证,尤其是第一个。坦率地说,这样做的整个想法似乎很糟糕。)
无论如何,既然您提到了性能原因,您可能会考虑更改为 Perl 或 Python 而不是 shell,不是因为简单的比较,而是因为它们允许您在不调用外部程序(例如grep
、sed
、cut
或jq
)的情况下执行更多操作。另外,性能优化的第一条规则:衡量差异。
答案2
# $A = "x" && $B = "y"
case ${A:--}/${B:--} in 'x/y' ) let a=a+1;; esac
# $A = "x" && $B != "y"
case $A in 'x' ) case $B in '' | ??* | [!y] ) let a=a+1;; esac;; esac