Unix管道用于命令参数

4

我希望了解如何使用管道将标准输出作为其他命令的参数传递。

例如,考虑以下情况:

ls | grep Hello

grep的结构遵循这个模式:grep 搜索词 要搜索的文件路径。在我所举的例子中,单词“Hello”被作为搜索词,并将ls的结果作为要搜索的文件。但是如果我想交换它们呢?如果我想让ls的标准输出成为搜索词,并将grep后面的参数作为要搜索的文件路径?一般情况下,我希望能够控制管道将前一个命令的标准输出填充到哪个参数上。这是可能的吗?还是这取决于命令脚本(例如grep)的编写方式?谢谢您的帮助!
2个回答

9

grep本身会被构建成这样,如果您没有指定文件名,它将打开stdin(因此获取ls的输出)。这里没有真正的通用机制-只是惯例。

如果您希望ls的输出成为搜索项,可以通过shell完成。利用子shell和替换,如下:

$ grep $(ls) filename.txt

在这个场景中,ls 在子shell中运行,并且它的stdout被捕获并插入命令行作为grep的参数。请注意,如果ls的输出包含空格,这会对grep造成困扰。

7

这方面基本上有两种选择:shell命令替换和xargs。Brian Agnew刚刚写了关于前者的内容。 xargs是一个实用程序,它将stdin转换为要执行的命令的参数。因此,您可以运行

ls | xargs -n1 -J % grep -- % PathOfFileToBeSearched

针对ls输出的每个文件,它会运行 grep -e filename PathOfFileToBeSearched 命令,在指定的其他文件中查找 ls 输出的文件名。这是一个不寻常的xargs调用方式;通常,它用于在命令末尾添加一个或多个参数,而在此处应准确地在特定位置添加一个参数,因此我使用了-n-J参数来排列。更常见的用法可能类似于:

ls | xargs grep -- term

要搜索由ls输出的所有文件中的term。当然,如果您只想在当前目录中搜索文件,则可以更简单地执行此操作,无需使用管道:

grep -- term *

同样地,在您反转的排列中,

for filename in *; do
  grep -- "$@" PathOfFileToBeSearched
done

有一个重要的 xargs 注意事项:由 ls 生成的文件名中的空格字符不会被很好地处理。为了解决这个问题,如果您有 GNU 实用程序,可以使用 find

find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 -n1 -J % grep -- % PathOfFileToBeSearched

使用NUL字符代替空格来分隔文件名


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接