比较以下命令:
cat f.txt | grep "someText"
grep "someText" f.txt
他们似乎都工作。但是 cat 的文档说 cat 输出文件的内容而不是文件名,而 grep 命令采用文件名而不是文件内容(如果我错了,请纠正我),那么为什么第一个命令可以工作,因为它为 grep 提供了文件内容而不是文件名。
另一个问题:它们都有效,但为什么要使用第一行而不是第二行,第一行只是多余的?
答案1
在你的第一个例子中
cat f.txt | grep "someText"
grep
没有获取文件名参数,只有要搜索的字符串。在这种情况下,grep
将从标准输入读取要搜索的文本。在这种情况下,标准输入是从 的输出中通过管道输入的cat f.txt
,输出文件的内容不是文件名。
您还可以执行以下操作来grep
从标准输入读取数据:
< f.txt grep "someText"
usingcat
本身通常是多余的(独立于grep
),并且可以通过上面的输入重定向来替换。我将始终在您的示例中使用第二种形式,除非您必须对输入进行一些预处理。
答案2
cat
在第一个示例中使用 as 有两个主要原因:
作为其他命令或长而复杂的命令管道的占位符。
例如,如果您正在编写一个脚本或单行程序来处理一个大文件,或者来自
psql
/mysql
或wget
或jq
等查询的数据,您可以将(部分)输入保存到示例文件中并用作cat sample
输入,直到获得脚本或一行右。然后只需将 替换cat
为实际命令或管道即可。同样,如果您的目的是教某人有关管道的知识,那么它是一个有用的占位符。
(很多人称其为 Cat 或 UUOC 的无用使用。这很大程度上是因为他们自鸣得意,喜欢用自己所谓的卓越知识来击败新手,而不是帮助他们学习——使用
cat
而不是帮助他们学习的可怕罪行<
是如此重要,以至于不能被忽视,就好像它只是一个微不足道的细节,世界即将终结,这将是一个cat
灾难。)当您不希望程序知道输入文件的文件名时。例如
cat * | grep ...
不同于grep ... *
.这通常并不重要,但一旦发生,就会非常重要。
对于
grep
,您可以使用 禁止列出文件名-h
,但其他程序没有这样的选项 -wc
例如,将始终输出文件名和每个文件的计数,即使您不需要它们。当然,您可以使用类似的东西,但是如果您正在执行类似的操作并且生成的文件名列表超出了 shell 的最大命令行长度,
wc * | tail -1 | awk '{print $1, $2, $3}'
那么这不起作用- 在这种情况下,您会得到多个“总”行(并且无法区分实际的总行和输出中名为“total”的文件)。find . -type f -exec wc {} +
find
wc
find . -type f -exec cat {} + | wc
find
无论找到多少个文件(没有找到、一个或多个),仅生成一行输出(总计) 。(
wc
确实需要两者--totals-only
和--no-totals
选项。)