在击管,标准输入和命令行参数(Pipe, standard input and command li

2019-07-20 10:47发布

考虑:

command1 | command2

被用作命令2或作为命令行参数标准输入命令1的输出,以命令2?

例如,

cat test.sh | grep "hehe"

什么是它不使用管道等价形式?

我试过了

grep "hehe" $(cat test.sh)

它似乎并没有被正确的。

Answer 1:

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的基本目录中,你想知道的情况。)

grep例子中,会发生什么情况是,内容test.sh被读出并分成空白分隔的单词,并且每个这样的单词被作为参数提供给grep 。 由于grep后治疗的话"hehe" (其中grep ,当然不会看到双引号-他们不是在这种情况下需要;作为一般规则,使用单引号,而不是双引号,尤其是在复杂的字符串像其中经常使用shell元字符,正则表达式)......就像我说的, grep后治疗的话"hehe"作为文件名,并尝试打开每个文件,通常是惨淡经营失败,因为不存在的文件。 这就是为什么符号是不是在这方面的适当。


重新审视这个问题之后,还有更多的可以说 - 那尚未说。

首先,许多Unix命令被设计为“过滤器”的工作; 他们阅读一些文件输入,改造它以某种方式,并将结果写入到标准输出。 这样的命令被设计用于命令管线中使用。 例子包括:

  • grep的
  • troff的和亲戚
  • AWK(有告诫)
  • SED
  • 分类

所有这些过滤器具有相同的特性:他们采取命令行选项来控制自己的行为,然后他们要么读指定作为命令行参数的文件或者,如果没有这样的论点,他们阅读他们的标准输入。 有的(如sort ),可以有选择的控制,他们的输出变的,而不是标准输出,但是这是比较少见的。

有一些纯粹的过滤器- tr是一个这样的-即严格标准输入读取和写入到标准输出。

其他命令有不同的行为。 雷蒙德提供了“为命令类型分类法Unix编程艺术 ”。

有些命令生成标准输出文件名列表-两个经典的lsfind

有时候,你想从一个文件名发电机作为命令行参数过滤器应用于输出。 还有,做自动程序-这是xargs

传统上,你可以使用:

find . -name '*.[chyl]' | xargs grep -n magic_name /dev/null

这将产生与扩展“文件的完整列表.c ”,“ .h ”,“ .y ”和“ .l ”(C源,标题的Yacc和Lex文件)。 作为列表被读xargs ,这将产生具有命令行grep -n magic_name /dev/null开始和每一个字(由空格分隔)作为参数。

在过去,UNIX文件名不包含空格。 在Mac和Windows的影响力,这样的空间现在常见的地方。 的GNU版本findxargs具有互补选项来解决这个问题:

find . -name '*.[chyl]' -print0 | xargs -0 grep -n magic_name /dev/null

该“ -print0 ”选项指的是“终止打印文件名的NUL‘\ 0’”(因为不能出现在一个(简单)的文件名中的字符只有“/”和NUL,显然,“/”可以出现在路径名)。 相应的“ -0 ”告诉xargs查找由NUL代替空格隔开名终止名。



Answer 2:

重定向的另一种形式是进程替换。

grep "hehe" <(cat test.sh)

相当于:

grep "hehe" test.sh

这既看的内容test.sh本身。

虽然,因为它已经注意到,此命令:

grep "hehe" $(cat test.sh)

会在文件名test.sh ,并用它们作为论据grep 。 所以,如果test.sh包括:

scriptone
scripttwo

然后grep是要在每个这些文件的内容,以寻找“嘿嘿”。



Answer 3:

它作为标准输入。

尝试:

grep "hehe" - $(cat test.sh)

这可能是错误的; 我无法测试出来这台计算机上。 如果你这样做,而不管像你这么干,grep的对待最后一个参数为文件名,例如,查找一个名为[test.sh内容]文件。 如果你传递一个 - (或者不把最后一个参数),你告诉它使用标准输入作为文件。

你也可以通过用grep文件扫描至:

grep "hehe" test.sh

...但你似乎会问更广义的bash的问题,不是一个真正的grep的使用问题,所以这可能不是太大的帮助。



Answer 4:

什么是使用命令行参数一个bash管道的相同呢?

管道和命令行参数是不可互换的不同形式的输入。 如果一个程序可以让你有两种等价形式,即单靠方案的选择。 (源代码,命令行参数显示为一个可变文本,而管显示为打开的文件,包括标准输入和标准输出。Bash的I / O重定向的语法,这里lateron使用,在技术上属于命令行参数,即使写对旁边的命令行...)

但是,让我们迂腐,也解答一下:

什么是bash的管道,而不使用bash的管道字符等效?

答: cat test.sh | grep "hehe" cat test.sh | grep "hehe" ,相当于

grep "hehe" < <(cat test.sh)

说明:

  • 管道重定向标准输出的命令到另一个标准输入。 设置标准输入的来源,我们可以使用输入重定向( < … ),而不是使用管道字符。
  • 然而,仅仅使用输入重定向( grep "hehe" < test.sh )不等同于管道,因为它使用一个文件作为源标准输入,而管使用输出的命令cat test.sh )。 那么除此之外,我们添加进程替换<(…)从文件从一个命令输入代替输入。
  • 当然,这个例子困惑,因为这两个变体具有同样的效果:

     grep "hehe" < test.sh grep "hehe" < <(cat test.sh) 

    但在技术上,从文件中输入仍然是一个不同的机制不是从从文件中获取输入命令的输出输入。

来源: 高级Bash脚本手册,工艺替代部分 (开始于“其他的一些习惯”读书)。



文章来源: Pipe, standard input and command line arguments in Bash
标签: bash pipe