Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash中的管道、标准输入和命令行参数_Bash_Pipe - Fatal编程技术网

Bash中的管道、标准输入和命令行参数

Bash中的管道、标准输入和命令行参数,bash,pipe,Bash,Pipe,考虑: command1 | command2 command1的输出是用作command2的标准输入还是用作command2的命令行参数 比如说, cat test.sh | grep "hehe" 如果不使用管道,其等效形式是什么 我试过了 grep "hehe" $(cat test.sh) 它似乎不正确。它被用作标准输入 尝试: 这可能是错误的;我不能在这台计算机上测试它。如果像您尝试的那样不使用管道,grep会将最后一个参数视为文件名,即查找名为[contents of test

考虑:

command1 | command2
command1的输出是用作command2的标准输入还是用作command2的命令行参数

比如说,

cat test.sh | grep "hehe"
如果不使用管道,其等效形式是什么

我试过了

grep "hehe" $(cat test.sh)

它似乎不正确。

它被用作标准输入

尝试:

这可能是错误的;我不能在这台计算机上测试它。如果像您尝试的那样不使用管道,grep会将最后一个参数视为文件名,即查找名为[contents of test.sh]的文件。如果你给它传递了一个-(或者没有放最后一个参数),你会告诉它使用stdin作为文件

您也可以将要扫描的文件传递给grep:

grep "hehe" test.sh
…但您似乎问的更多的是一般化的bash问题,而不是grep用法问题,所以这可能没有太大帮助

grep "hehe" < 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命令被设计成“过滤器”;他们从一些文件中读取输入,以某种方式进行转换,然后将结果写入标准输出。此类命令是为在命令管道中使用而设计的。例子包括:

  • 格雷普
  • 特罗夫及其亲属
  • awk(带警告)
  • 塞德
  • 分类
所有这些过滤器都具有相同的常规行为:它们使用命令行选项来控制其行为,然后读取指定为命令行参数的文件,或者,如果没有此类参数,则读取其标准输入。有些(如
排序
)可以使用选项来控制其输出的位置,而不是标准输出,但这种情况相对少见

有几个纯过滤器-
tr
就是这样一个过滤器-,它严格读取标准输入并写入标准输出

其他命令具有不同的行为。Eric Raymond为“”中的命令类型提供了分类法

一些命令在标准输出上生成文件名列表-两个经典命令是
ls
find

有时,您希望将文件名生成器的输出应用为筛选器的命令行参数。有一个程序可以自动完成这项工作,它是
xargs

通常,您会使用:

find . -name '*.[chyl]' | xargs grep -n magic_name /dev/null
这将生成扩展名为“
.c
”、“
.h
”、“
.y
”和“
.l
”的完整文件列表(c源代码、标题、Yacc和Lex文件)。当列表由
xargs
读取时,它将创建命令行,在开始处使用
grep-nmagic\u name/dev/null
,每个单词(用空格分隔)作为参数

在过去,Unix文件名不包含空格。在Mac和Windows的影响下,这样的空间现在很普遍。
find
xargs
的GNU版本具有处理此问题的补充选项:

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

-print0
”选项意味着“打印以NUL“\0”结尾的文件名(因为(简单)文件名中不能出现的字符只有“/”和NUL,显然,“/”可以出现在路径名中)。相应的“
-0
”告诉
xargs
查找以NUL结尾的名称,而不是以空格分隔的名称。

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

grep "hehe" <(cat test.sh)
它们都查看
test.sh
本身的内容

然而,如前所述,此命令:

grep "hehe" $(cat test.sh)
test.sh
中查找文件名,并将其用作
grep
的参数。因此,如果
test.sh
包含:

scriptone
scripttwo

然后,grep将在每个文件的内容中查找“hehe”。

使用命令行参数的bash管道的等价物是什么?

管道和命令行参数是不同形式的输入,不能互换。如果一个程序允许您拥有两者的等效形式,则只能选择该程序。(在源代码中,命令行参数显示为变量中的文本,而管道显示为打开的文件,包括stdin和stdout.Bash I/O重定向语法,如下文所述,从技术上讲不属于命令行参数,即使在命令行上写在命令行参数的旁边……)

但让我们学究式地回答这个问题:


在不使用bash-pipe字符的情况下,bash-pipe的等价物是什么?

回答:
cat test.sh | grep“hehe”
相当于

grep "hehe" < <(cat test.sh)
但从技术上讲,来自文件的输入与从文件获取输入的命令输出的输入仍然是不同的机制


来源:(从“其他用法”开始阅读。)

在test.sh中读取每个单词,并查找与该单词同名的文件,并在这些文件上进行greps(通常成功率非常有限)。反勾号是命令替换,就像grep "hehe" $(cat test.sh)
scriptone
scripttwo
grep "hehe" < <(cat test.sh)
grep "hehe" < test.sh
grep "hehe" < <(cat test.sh)