【问题标题】:Use of pipes in backticks在反引号中使用管道
【发布时间】:2011-08-24 06:25:55
【问题描述】:

我正在尝试使用管道运行命令但收到错误:

echo abc | `echo "grep a | grep b"`
grep: |: No such file or directory
grep: grep: No such file or directory
grep: b: No such file or directory

代码有什么问题?

预期结果是执行以下命令:

echo abc | grep a | grep b

结果

abc

【问题讨论】:

    标签: bash pipe backticks


    【解决方案1】:

    不清楚您要做什么,但这是您正在做的事情:

    echo "grep a | grep b"
    

    输出字符串grep a | grep b

    这是反引号的输出。您在 shell 需要命令的位置使用反引号,所以 "grep 'a' '|' 'grep' 'b'" 尝试作为命令行,所有标记都按字面解释(我添加了单引号以使其更清晰,希望如此),因此 shell 忽略来自 echo 的输入,而是尝试查找命名文件中的正则表达式a。您显然没有名为“|”、“grep”或“b”的文件,因此您会收到一条错误消息。

    你可能想要的是

    echo abc | grep a | grep b
    

    在“echo”的输出中搜索“a”,然后在第一个 grep 的输出中搜索“b”。因为abc匹配正则表达式a,所以第一个grep成功,所以打印匹配行;并且因为它也匹配正则表达式b,所以它也被最终的grep 打印出来。

    要对此进行扩展,请尝试以下操作:

    sh$ echo abc; echo bcd; echo xya
    abc
    bcd
    xya
    
    sh$ ( echo abc; echo bcd; echo xya ) | grep a  # print lines matching a
    abc
    xya
    
    sh$ (echo abc; echo bcd; echo xya ) | grep a | grep b  # print lines matching a and b
    abc
    

    不清楚为什么要使用反引号;如果这不是您想要实现的目标,请更详细地说明您想要实现的目标。

    如果你想找到匹配 a 或 b 的行,试试这个:

    sh$ ( echo abc; echo bcd; ) | grep '[ab]'
    

    【讨论】:

    • 不知道为什么,但我认为那是 php 代码:我现在删除了我的答案,因为它与这个主题无关
    【解决方案2】:

    只有当你让 bash 解析器看到它时,管道字符才是特殊的。您使用“”引用它,因此它不再特殊,grep 认为您希望它从文件 |grepb 中 grep 字符串 a

    一般来说,一旦你转义了作为 shell 语法一部分的特殊字符,你就不能在以后取消转义(因为这样就无法处理实际称为 | 的文件 - 而不是好主意,但它可能的,而且 bash 不应该无法处理它。)

    让此类字符再次被视为特殊字符的唯一方法是将其重新提交给 shell 解释器的全新调用,这就是 Robert Martin 的解决方案所做的。

    【讨论】:

      【解决方案3】:

      Triplee 的解释与我认为正在发生的事情非常接近(如果不是说完全相同的话)。 “Clasic Shell Scripting” [Robbins & Beebe],第 7.8.1 节,实际上对与我原来的问题相关的问题有一个很好的解释。

      如果你写

      listpage="ls | more" 
      $listpage
      

      然后你会遇到类似的问题,'|' & 'more' 被视为 ls 的参数。给出的原因是,在 shell 完成变量替换时(步骤 5/10),原始输入已经被分解为标记(其中 | 是一个)(步骤 1/10)。所以'|'失去其特殊意义并被视为论据。

      但是,如果你写:

      eval $listpage
      

      eval 使 shell 在第 1 步重新启动,这里的 '|'字符被视为特殊标记。

      【讨论】:

      【解决方案4】:

      这部分错了:

      $ `echo "grep a | grep b"`
      

      因为反引号不理解管道。试试这个做同样事情的替代方案:

      $ echo "grep a | grep b" | sh
      

      【讨论】:

      • 它自己什么也不做。第一个 grep 将尝试读取标准输入,但标准输入已经绑定以将命令回显到 sh 的管道中。
      猜你喜欢
      • 1970-01-01
      • 2018-01-14
      • 2014-09-26
      • 2011-09-30
      • 2013-06-07
      • 2014-09-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多