在反推中使用管道

时间:2011-08-24 06:25:56

标签: bash pipe backticks

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

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

4 个答案:

答案 0 :(得分:3)

目前还不清楚你要做什么,但这就是你在做什么:

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]'

答案 1 :(得分:2)

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

一般情况下,一旦你转义了一个属于shell语法的特殊字符,你就不能在以后使用它(因为那样就无法处理实际上被称为b的文件 - 不是一个好主意,但 是可能的,而bash不应该无法处理它。)

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

答案 2 :(得分:2)

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

如果你写

listpage="ls | more" 
$listpage

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

但是,如果你写:

eval $listpage

eval导致shell在步骤1重新启动,其中“|”字符被视为特殊标记。

答案 3 :(得分:0)

这部分错了:

$ `echo "grep a | grep b"`

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

$ echo "grep a | grep b" | sh