考虑:
command1 | command2
Run Code Online (Sandbox Code Playgroud)
command1的输出是用作command2的标准输入还是用作command2的命令行参数?
例如,
cat test.sh | grep "hehe"
Run Code Online (Sandbox Code Playgroud)
没有使用管道的等效形式是什么?
我试过了
grep "hehe" $(cat test.sh)
Run Code Online (Sandbox Code Playgroud)
而且似乎不正确.
Jon*_*ler 14
grep "hehe" < test.sh
Run Code Online (Sandbox Code Playgroud)
输入重定向 - 当然仅适用于单个文件,而cat适用于任意数量的输入文件.
考虑一下这些符号:
grep "hehe" $(cat test.sh)
grep "hehe" `cat test.sh`
Run Code Online (Sandbox Code Playgroud)
在这方面,这些是相同的; $(cmd)在嵌套用法中使用' '表示法要容易得多,例如:
x=$(dirname $(dirname $(which gcc)))
x=`dirname \`dirname \\\`which gcc\\\`\``
Run Code Online (Sandbox Code Playgroud)
(这会为您提供安装GCC的基本目录,以防您想知道.)
在该grep示例中,所发生的test.sh是读取内容并将其拆分为空格分隔的单词,并且每个这样的单词作为参数提供grep.由于grep后话治疗"hehe"(其中grep,当然,也没有看到双引号-他们不是在这种情况下需要;作为一般规则,使用单引号,而不是双引号,尤其是在复杂的字符串像正则表达式经常使用shell metacharacters)...正如我所说的那样,grep将文字名后面的单词"hehe"视为文件名,并尝试打开每个文件,因为文件不存在,通常会失败.这就是为什么符号在这种情况下不合适的原因.
在重新审视这个问题后,还有更多可以说的内容 - 尚未说过.
首先,许多Unix命令被设计为"过滤器"; 他们从一些文件中读取输入,以某种方式对其进行转换,并将结果写入标准输出.此类命令旨在用于命令管道.例子包括:
所有这些过滤器都具有相同的一般行为:它们使用命令行选项来控制它们的行为,然后它们读取指定为命令行参数的文件,或者,如果没有这样的参数,它们读取它们的标准输入.有些(比如sort)可以选择控制输出的位置而不是标准输出,但这种情况相对不常见.
有一些纯滤波器 - tr就是这样 - 严格读取标准输入并写入标准输出.
其他命令有不同的行为.Eric Raymond在" UNIX编程的艺术 "中为命令类型提供了分类.
一些命令在标准输出上生成文件名列表 - 两个经典是ls和find.
有时,您希望将文件名生成器的输出应用为过滤器的命令行参数.有一个程序自动执行 - 它是xargs.
传统上,你会使用:
find . -name '*.[chyl]' | xargs grep -n magic_name /dev/null
Run Code Online (Sandbox Code Playgroud)
这将生成一个包含扩展名' .c',' .h',' .y'和' .l'(C源代码,标题,Yacc和Lex文件)的完整文件列表.当列表被读取时xargs,它将grep -n magic_name /dev/null在开头创建命令行,并且每个单词(由空格分隔)作为参数.
在过去,Unix文件名不包含空格.在Mac和Windows的影响下,这样的空间现在已经很普遍了.GNU版本find并xargs有补充选项来处理这个问题:
find . -name '*.[chyl]' -print0 | xargs -0 grep -n magic_name /dev/null
Run Code Online (Sandbox Code Playgroud)
' -print0'选项意味着"打印文件名由NUL'\ 0'终止"(因为唯一不能出现在(简单)文件名中的字符是'/'和NUL,显然,'/'可以出现在路径中名).相应的' -0'告诉xargs查找由NUL终止的名称而不是空格分隔的名称.
另一种重定向形式是进程替换.
grep "hehe" <(cat test.sh)
Run Code Online (Sandbox Code Playgroud)
相当于:
grep "hehe" test.sh
Run Code Online (Sandbox Code Playgroud)
它们都看着test.sh自己的内容.
虽然,正如已经指出的那样,这个命令:
grep "hehe" $(cat test.sh)
Run Code Online (Sandbox Code Playgroud)
查找文件名test.sh并将其用作参数grep.所以,如果test.sh包括:
scriptone
scripttwo
Run Code Online (Sandbox Code Playgroud)
然后grep将在每个文件的内容中寻找"hehe".