3

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

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

4 回答 4

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]'
于 2011-08-24T06:57:20.973 回答
2

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

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

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

于 2011-08-24T06:40:03.147 回答
2

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 步重新启动,其中 '|' 字符被视为特殊标记。

于 2011-08-25T03:20:56.783 回答
0

这部分是错误的:

$ `echo "grep a | grep b"`

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

$ echo "grep a | grep b" | sh
于 2011-08-24T06:32:15.090 回答