2016-11-22 37 views
4

我有我的shell脚本的if线,看起来像这样:为什么测试会说出意外的括号?

if [ 0 -lt 2 -o (0 -gt 3) ] 

,这给出了错误:

line 3: syntax error near unexpected token `(' 

所以我看着man test,以确保括号中的支持,果然,非常接近手册页的顶部,他们是!是什么赋予了!?

上面的示例与代码并不完全匹配,因为我试图清理它以证明一点,但如果需要上下文,则这是my repo

编辑:改变了if行以匹配错误。

+1

仅供参考,这是一个http://www.shellcheck.net/可以自动检测到的错误。 –

回答

5

括号被传递到test命令作为参数[ ... ]表达式是输入test命令的另一种方式。唯一的区别是[命令的最后一个参数必须是]

所以,你应该逃避括号就像你传递给命令的任何其他参数,以避免外壳的解释:

if [ \($# -lt 2 \) -o \($# -gt 3 \) ] 

另外,使用单引号:

if [ '(' $# -lt 2 ')' -o '(' $# -gt 3 ')' ] 

从信息页:

`test' 
`[' 
      test EXPR 

    Evaluate a conditional express ion EXPR and return a status of 0 
    (true) or 1 (false). Each operator and operand must be a separate 
    argument. 

通过

if builtin test \($# -lt 2 \) -o \($# -gt 3 \) 
+1

+1可能有用于表明POSIX(〜UNIX)规范将参数数量限制为4 (搜索> 4):[稍高于此链接](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html#tag_20_128_06) – sorontar

+0

也值得注意的(从相同的链接页面): “用于指定'-a'和'-o'二进制基元的XSI扩展以及'('和')'运算符_已被标记为obsolescent_(使用它们的许多表达式根据所评估的特定表达式由语法明确定义)”。建议使用单独的'test' /'['语句,并将它们与'&&'/'||'结合使用。 – mklement0

3

您在[ ... ]中有不必要的(...),它们未转义且未引起引起语法错误。

您可以使用它代替:

[[ $# -lt 2 || $# -gt 3 ]] 

或者使用:

[[ $# -lt 2 ]] || [[ $# -gt 3 ]] 
+0

有趣的是,我认为这是因为引用,但我猜这个表达式'$#-lt 2'总是会返回一些东西 - 无论是'0'还是'1',所以它不是一个引用问题。所以我认为你是对的。 –

+1

但是请注意,shell将''与[''不同于'[''。除了其他差异之外,它允许使用未转义的括号。所以提问者实际上可以将他的''[...]'改成'[[...]]'并保留他的圆括号。 –

+0

是的,即使它们在这里没有必要,parens'(...)'是增加shell中条件表达式优先级的方式 - 因此,每个rob mayoff注释,'[[...]]语法将允许在条件中更加可读地使用parens。 –

3

虽然这种解决方案并不直接回答这个问题,但这里是采用C风格arithmetic expressions的另一种方法,如果你处理的数字是有效的:顺便说一下,如下的表达式可以改写在bash

#!/bin/bash 

if (("$#" < 2 || "$#" > 3)); then 
+3

这不回答'为什么测试说出乎意料的括号?'问题。如果你想补充现有的答案,发表评论。 –

+1

@MarcinOrlowski:完全同意你的看法,强调这一点,如果作者可以使用这种比较方法,那么他最终不会以这个错误结束。认为这是值得一个正确的答案。 – Inian

+1

这不提供问题的答案。要批评或要求作者澄清,请在其帖子下方留言。 - [来自评论](/ review/low-quality-posts/14366915) –

相关问题