我正在尝试使用管道运行命令但收到错误:
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
答案 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