代码之家  ›  专栏  ›  技术社区  ›  Brett Ryland

bash[:大于符号的参数太多

  •  4
  • Brett Ryland  · 技术社区  · 8 年前

    这不是一个真正的问题(虽然我最后有一个问题),而是一个我想分享的问题的解决方案,以防它帮助到其他人。

    我得到的最长时间 bash: [: too many arguments 打开新终端时(特别是安装了bash完成macport的OS X上的iTerm2)。此错误源于线路 if [ -n "$BASH_VERSION" -a -n "$PS1" -a -z "$BASH_COMPLETION_COMPAT_DIR" ]; then 在文件中 /opt/local/etc/bash_completion 我终于找到了问题的根源 export PS1='>' 在我的 .bash_profile 。将PS1更改为其他内容(例如。 '> ' )修复了bash完成的问题。

    在OSX和Debian中的一些实验表明,当添加额外的表达式( -a -o )进入测试( [ ] )在涉及的表达式之后 '>' 例如。,

    > A='>'; if [ -n "$A" ]; then echo "yes"; fi
    yes
    > A='>'; if [ -n "$A" -a -n "$A" ]; then echo "yes"; fi
    bash: [: too many arguments
    > A='> '; if [ -n "$A" -o -n "$A" ]; then echo "yes"; fi
    yes
    > A='>'; if [ -n "$A" -o -n "Hello" ]; then echo "yes"; fi
    bash: [: too many arguments
    > A='>'; if [ -n "Hello" -a -n "$A" ]; then echo "yes"; fi
    yes
    

    这是bash中的(已知)bug吗?

    2 回复  |  直到 8 年前
        1
  •  4
  •   mklement0    8 年前

    只要字符串存储在 $A 不是 操作人员 那个 [ / test 正如您所发现的,只需添加一个空格就足够了。

    当然,“大于”应该被解释为一个字符串?它与“>”一起工作毕竟

    否,内容 $A美元 解释为一个字符串。(如果你想要,你就得用 [[ 相反,它是在一个特殊的上下文中解析的,更像您从传统编程语言中期望的那样。)

    [ ( 测验 )是一个内置的(在大多数系统上也作为一个外部实用程序存在),因此使用 命令语法 ,这意味着:

    • shell执行其扩展 第一 - $A美元 在这种情况下,引用被替换为变量的内容。
    • 然后将结果传递给 [

    因此,从 [ ,它最终看到的操作员与否并不重要- > 在你的例子中-来自 字面意义的 或存储在 变量 .

    但请注意 空白很重要 :通过 > (无空格)被解释为运算符; > 相比之下 ><space> 不是-因为确切的文字是 更多 而不仅仅是操作员。


    底线是:

    • 您正在使用的bash完成脚本是 不坚固 .
    • 正如@chepner在对该问题的评论中所述, POSIX recommends not using -o / -a 为了避免你遇到的歧义(强调我的):

    指定 -a和-o 二进制主键和“(”和“)”运算符已标记为过时。(许多使用它们的表达式是 定义模糊 取决于被评估的特定表达式的语法。)

    • 具体而言,使用单独 [ ... ] 与联接的表达式 && (而不是 -一个 )和 || (而不是 -o型 )解决了问题:

      [ -n "$BASH_VERSION" ] && [ -n "$PS1" ] && [ -z "$BASH_COMPLETION_COMPAT_DIR" ]
      

    或者,更简单地说,利用非空字符串求值为true:

    [ "$BASH_VERSION" ] && [ "$PS1" ] && [ -z "$BASH_COMPLETION_COMPAT_DIR" ]
    

    请注意,虽然 -一个 -o型 介绍 模棱两可 ,它们是 安全问题 -您不能通过使用注入任意代码。

        2
  •  2
  •   Toby Speight    8 年前

    如果要使用两个或更多条件,则应使用

    if [ condition1 ] && [condition2 ]
    

    if [ condition1 ] || [condition2 ]
    

    因此,在您的情况下(首先是“and”):

    A='>'; if [ -n "$A" ] && [ -n "$A" ]; then echo "yes"; fi
    

    对于“或”,如果:

    A='>'; if [ -n "$A" ] || [ -n "Hello" ]; then echo "yes"; fi
    

    但请注意,第二次检查 [ -n "Hello" ] 总是正确的,所以最好删除它。

    你可能对 shellcheck 验证bash脚本语法。