感叹号和太多参数

时间:2016-02-07 11:25:33

标签: bash

我尝试在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以惊叹号开头,仍然会失败。这让我很担心,因为我有很多脚本以相同的方式测试字符,如果值包含感叹号,可能会意外地失败,所以我可以为此找到一个好的解决方法。

2 个答案:

答案 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" = '*' ]

看看the Bash Hackers' Wiki