我尝试在bash脚本中设置条件但是我遇到了一个异常错误; bash抱怨说有太多论点,但对我来说一切似乎都是正确的:
[ "${foo:0:1}" = '!' -o "$foo" = '*' ]
很简单,如果$foo
是星号,或者以感叹号开头,测试应该会成功。
但是,当$foo
以感叹号开头时,我在bash中收到以下错误:
bash: [: too many arguments
奇怪的是,如果我省略第二个条件,它就能正常工作:
[ "${foo:0:1}" = '!' ]
所以似乎评估感叹号的"${foo:0:1}"
会以某种方式干扰逻辑或条件,任何人都可以解释这里发生了什么,以及解决它的最佳方法是什么?
我测试的内容似乎并不重要,例如:
[ "${foo:0:1}" = 'z' -o "$foo" = '*' ]
如果$foo
以惊叹号开头,仍然会失败。这让我很担心,因为我有很多脚本以相同的方式测试字符,如果值包含感叹号,可能会意外地失败,所以我可以为此找到一个好的解决方法。
答案 0 :(得分:3)
您可以通过拆分表达式来解决此问题:
[ "${foo:0:1}" = '!' ] || [ "$foo" = '*' ]
因此,Bash不会误解您对'!'
的含义 - 如果是字符串或not
运算符。
答案 1 :(得分:2)
除非您的目标是POSIX兼容性,否则在使用bash时,请[[
优先于[
。它更安全,更容易,更强大。
例如,您可以使用regular expressions:
[[ $foo =~ '^(!|\*$)' ]]
[[
构造支持||
和&&
,您应该优先考虑-o
和-a
:
[[ "${foo:0:1}" = '!' || "$foo" = '*' ]]
历史记录扩展在变量展开之前发生,因此foo
包含!
不会因历史记录扩展而导致问题。可能发生的事情是[
将!
视为否定运算符:
$ help [
[: [ arg... ]
This is a synonym for the "test" builtin, but the last
argument must be a literal `]', to match the opening `['.
[[ ... ]]: [[ expression ]]
Returns a status of 0 or 1 depending on the evaluation of the conditional
expression EXPRESSION. Expressions are composed of the same primaries used
by the `test' builtin, and may be combined using the following operators
( EXPRESSION ) Returns the value of EXPRESSION
! EXPRESSION True if EXPRESSION is false; else false
完整命令(例如,如果foo='!abcd'
)变为:
[ '!' = '!' -o '!abcd' = '*' ]
将解析哪些:
NOT(= '!' -o '!abcd' = '*')
如果你尝试使用内部表达式,你会得到同样的错误:
$ [ = '!' -o a = a ]
sh: [: too many arguments
常见的解决方法是在字符串前添加另一个字符:
[ "z${foo:0:1}" = 'z!' -o "$foo" = '*' ]