【问题标题】:syntax error near unexpected token `&' (using "|&")意外标记“&”附近的语法错误(使用“|&”)
【发布时间】:2013-12-31 11:29:39
【问题描述】:

我在下一个意外标记& 附近有语法错误: 在 bash 脚本中它是这样的:

#!/bin/bash
var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null)|& grep real|awk '{print $2}'`

当我在 cli 上发出这个命令时,我得到了很好的输出,问题是当在脚本中调用它时,我可以从 var1 得到任何输出

./check_cdifonline.sh: command substitution: line 2: syntax error near unexpected token `&'
./check_cdifonline.sh: command substitution: line 2: `(/usr/bin/time cdifonline -CD 186821 -ALL >/dev/null) | & grep real | awk '{print $2}''

【问题讨论】:

  • 你为什么要&grep?您已经将输出传送到 grep
  • 因为我需要从 time 命令解析实际值,并且您需要先发送到 stderr 以获取 time 的输出,所以这是不可能的
  • 您的问题已被编辑以修复格式,但在第一个代码块的末尾仍有一些悬空字符。您可以通过编辑您的问题、删除第一个代码块并将其替换为您的实际代码的复制和粘贴来解决此问题,然后选择该块并单击 {} 将其格式化为代码(它只是缩进 4列)。

标签: bash shell awk


【解决方案1】:

感谢 Keith,我再也没有问题了,你拯救了我的一天 :) 所以 bash 版本是问题所在,避免 & 我没有错误,也感谢微调 :)

所以这适用于我的 bash 版本

#!/bin/bash
var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}'`

【讨论】:

    【解决方案2】:

    您可以使用序列|& 将 stdout 和 stderr 从一个进程传送到另一个进程。

    |& 之间不能有空格。 (csh 和 tcsh 允许空格;bash 不允许。)我怀疑您在交互式运行命令时碰巧在没有空格的情况下键入它;无论哪种方式,语法都是相同的。

    这个:

    foo |& bar
    

    是这个的简写:

    foo 2>&1 | bar
    

    更新:

    在 bash 3.2.25 中,|& 令牌无法识别;在 bash 4.1 中作为新功能添加。使用旧 bash 运行脚本,我会收到与您相同的错误消息。

    要使您的脚本与旧版本的 bash 兼容,只需执行等效的重定向而不使用 |& 运算符:

    #!/bin/bash
    var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}'`
    

    进一步改进:使用$(...) 而不是`...`

    #!/bin/bash
    var1=$((/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}')
    

    您还可以将grep 搜索合并到awk 命令中:

    #!/bin/bash
    var1=$((/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | awk '/real/ {print $2}')
    

    警告:除了验证它们在没有语法错误的情况下运行之外,我还没有彻底测试过这些。

    我仍然认为|&| & 之间没有区别。 /bin/bash 是否可能与您以交互方式运行的版本不同?试试/bin/bash --versionecho $BASH_VERSION

    【讨论】:

    • 我有同样的问题,没有空格,命令在 cli 中工作得很好,真的很讨厌
    • 我只是复制并粘贴了您问题中的代码并在我自己的系统上运行它。没有错误。 (我没有cdifonline 命令,但这不应该影响任何语法错误。)如果我以sh ./foo.bash 调用它,我会收到错误;你到底是如何运行脚本的?尝试将问题中的脚本复制并粘贴到一个新文件中并运行它。
    • 不,这很麻烦,因为我很伤心,在 cli 上一切都很好,但是在脚本中调用时出现此错误
    • 你试过我的建议了吗?您使用的是哪个版本的 bash (bash --version)?
    • bash --version GNU bash,版本 3.00.0(2)-release (sparc-sun-solaris2.6) 版权所有 (C) 2004 Free Software Foundation, Inc.
    【解决方案3】:

    尝试更改为:

    var1=$(/usr/bin/time cdifonline -CD 186821 -ALL >/dev/null | awk '/real/ {print $2}')
    

    【讨论】:

    • (/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null | awk '/real/ {print $2}') 不明确的输出重定向。
    • 仅此一项就可以输出吗? /usr/bin/time cdifonline -CD 186821 -ALL >/dev/null 如果是,那是什么?
    • /usr/bin/time cdifonline -CD 186821 -ALL >/dev/null real 3.2 user 0.4 sys 0.1
    • (/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null)|& grep real|awk '{print $2}' 1.3 当在 cli 上发出问题时我得到了我想要的只需要在 bash 脚本中将其设置为变量
    猜你喜欢
    • 2012-08-31
    • 2012-10-20
    • 2012-09-29
    • 2013-12-11
    • 1970-01-01
    • 1970-01-01
    • 2014-09-01
    • 2014-02-26
    相关资源
    最近更新 更多