grep "hehe" < test.sh
输入重定向 - 当然,仅适用于单个文件,而cat
适用于任意数量的输入文件。
考虑符号:
grep "hehe" $(cat test.sh)
grep "hehe" `cat test.sh`
这些在这种情况下是等效的;使用 ' 更容易$(cmd)
' 嵌套使用中的表示法,例如:
x=$(dirname $(dirname $(which gcc)))
x=`dirname \`dirname \\\`which gcc\\\`\``
(如果您想知道的话,这将为您提供安装 GCC 的基本目录。)
In the grep
例如,发生的情况是test.sh
被读取并分割成空格分隔的单词,并且每个这样的单词都作为参数提供grep
。自从grep
处理后面的单词"hehe"
(where grep
,当然,not请参阅双引号 - 在这种情况下不需要它们;作为一般规则,使用单引号而不是双引号,尤其是在复杂的字符串(如经常使用 shell 元字符的正则表达式)周围)...正如我所说,grep
处理后面的单词"hehe"
作为文件名,并尝试打开每个文件,通常会失败,因为文件不存在。这就是为什么该表示法在这种情况下不合适。
重新审视这个问题之后,还有更多可以说的——那些还没有说的。
首先,许多 Unix 命令被设计为“过滤器”;它们从某些文件中读取输入,以某种方式对其进行转换,然后将结果写入标准输出。此类命令设计用于在命令管道中使用。示例包括:
- cat
- grep
- 特罗夫和亲戚
- awk(有注意事项)
- sed
- sort
所有这些过滤器都具有相同的一般行为:它们采用命令行选项来控制其行为,然后读取指定为命令行参数的文件,或者如果没有此类参数,则读取标准输入。有些(比如sort
)可以有选项来控制其输出而不是标准输出的位置,但这相对不常见。
有几个纯粹的过滤器——tr
就是这样一种 - 严格读取标准输入并写入标准输出。
其他命令有不同的行为。 Eric Raymond 在“中提供了命令类型的分类法”UNIX 编程的艺术 http://www.catb.org/~esr/writings/taoup".
一些命令在标准输出上生成文件名列表 - 两个经典命令是ls
and find
.
有时,您希望将文件名生成器的输出应用为过滤器的命令行参数。有一个程序可以自动执行此操作 - 它是xargs
.
通常,您会使用:
find . -name '*.[chyl]' | xargs grep -n magic_name /dev/null
这将生成带有扩展名 ' 的完整文件列表.c
', '.h
', '.y
' and '.l
'(C 源代码、头文件、Yacc 和 Lex 文件)。当列表被读取时xargs
,它将创建命令行grep -n magic_name /dev/null
在开头和每个单词(用空格分隔)作为参数。
过去,Unix 文件名不包含空格。在 Mac 和 Windows 的影响下,这样的空间现在已经司空见惯了。 GNU 版本find
and xargs
有解决这个问题的补充选项:
find . -name '*.[chyl]' -print0 | xargs -0 grep -n magic_name /dev/null
The '-print0
' 选项表示“打印以 NUL '\0' 结尾的文件名”(因为不能出现在(简单)文件名中的唯一字符是 '/' 和 NUL,显然,'/' 可以出现在路径名中) 。相应的 '-0
' tells xargs
查找以 NUL 结尾的名称,而不是空格分隔的名称。