Bash 链式命令的stdin和命令替换中的命令
让我先介绍我的发现,然后在最后提出我的问题。(1) 仅适用于Bash 链式命令的stdin和命令替换中的命令,bash,zsh,Bash,Zsh,让我先介绍我的发现,然后在最后提出我的问题。(1) 仅适用于zsh,并且(2)、(3)同时适用于zsh和bash 1.命令替换标准 第一个打印猫:-:输入/输出错误;而第二个则产生ls的输出 2.管道后的链接命令 第一个命令不能正常工作cat遇到EOF并直接退出。但是第二种形式是有效的:第一行被读入a,而cat得到其余的部分 3.混合标准 在第一行的{}中,命令用于打印cmdline参数;在第二种形式中,该命令还从stdin读取一行 由于input()读取EOF,当第二个表单抛出时,第一个命令可
zsh
,并且(2)、(3)同时适用于zsh
和bash
1.命令替换标准
第一个打印猫:-:输入/输出错误;而第二个则产生ls
的输出
2.管道后的链接命令
第一个命令不能正常工作cat
遇到EOF
并直接退出。但是第二种形式是有效的:第一行被读入a
,而cat
得到其余的部分
3.混合标准
在第一行的{}
中,命令用于打印cmdline参数;在第二种形式中,该命令还从stdin
读取一行
由于input()
读取EOF
,当第二个表单抛出时,第一个命令可以成功运行
我的问题是:
{}
的表单与不带{}
的表单有什么区别李>
头部
和cat
是否可以按顺序读取相同的stdin
?第二种形式如何成功而第一种形式失败stdin
如何连接到原始命令的stdin(echo
)。谁先读?以及如何使stdin
保持打开状态,以便两个命令(python
和head
)可以按顺序读取相同的stdin
您没有考虑输入缓冲,它解释了您的大部分观察结果
head
每次需要数据时都会读取几千字节的输入,这使得它的效率更高。因此,它很可能会在任何其他进程有机会读取所有stdin之前读取所有stdin。这在案例2中是显而易见的,在案例2中,执行顺序可能更清晰
如果输入来自常规文件,
head
可以在终止之前返回到所用行的末尾。但由于管道是不可查找的,所以它不能这样做。如果您使用“here strings”--the,您就没有考虑输入缓冲,它解释了您的大部分观察结果
head
每次需要数据时都会读取几千字节的输入,这使得它的效率更高。因此,它很可能会在任何其他进程有机会读取所有stdin之前读取所有stdin。这在案例2中是显而易见的,在案例2中,执行顺序可能更清晰
如果输入来自常规文件,head
可以在终止之前返回到所用行的末尾。但由于管道是不可查找的,所以它不能这样做。如果您使用“herestrings”——头-n1;cat
是两个独立的命令。在这里,您在一个大括号组(不是命令替换)中使用head
,该组在stdin
上接收ls
的输出,然后您有效地调用cat
而不带任何参数——您希望发生什么?head
获得第一行,然后cat
获得其余行。也许是这个词把你弄糊涂了。我以前不知道正确的单词。是否应该对其进行分组
?不,不应该对其进行分组。对于管道(例如,foo | bar | baz
),每个管道将上一个命令的stdout
与下一个命令的stdin
连接起来。放置行终止符“;”两个命令之间的代码>与在脚本中使用两个单独的行是一样的。两者之间没有联系。如果需要第一个文件ls-1 | head-n1
。如果您想要除第一行以外的所有数据,那么ls-1 | tail-n+2
@david:inproduction|u data{head-n1;cat}
,我希望head
读取输入的开头,可能是8k左右,输出第一行并退出cat
不带参数将读取stdin中剩余的内容并将其打印到stdout。如果我执行一个函数head_plus(){head-n1;cat;}
,我也会有同样的期望。从这个意义上说,带括号的命令确实有一个连接,因为它们的读取方式与nput相同。不幸的是,head
是一个贪婪的bug,读取的内容远远不止一行,所以留给cat的输入更少。你预计会发生什么?我用不同的xxx
尝试了这个seq1xxx{head-n1;cat;}
,cat
从第1861行开始打印,而seq11861 | wc
告诉我它确实是8198字节。然而,seq 1 2000{head-n1;head-n1;}
只输出一行,第二行head
什么也得不到;cat是两个独立的命令。在这里,您在一个大括号组(不是命令替换)中使用head
,该组在stdin
上接收ls
的输出,然后您有效地调用cat
而不带任何参数——您希望发生什么?head
获得第一行,然后cat
获得其余行。也许是这个词把你弄糊涂了。我以前不知道正确的单词。是否应该对其进行分组
?不,不应该对其进行分组。对于管道(例如,foo | bar | baz
),每个管道将上一个命令的stdout
与下一个命令的stdin
连接起来。放置行终止符“;”两个命令之间的代码>与在脚本中使用两个单独的行是一样的。两者之间没有联系。如果需要第一个文件ls-1 | head-n1
。如果您想要除第一行以外的所有数据,那么ls-1 | tail-n+2
@david:inproduction|u data{head-n1;cat}
,我希望head
读取输入的开头,可能是8k左右,输出第一行并退出<代码>c
ls | echo $(cat)
ls | { echo $(cat) }
ls | { head -n1; cat}
ls | { read a; cat}
ls | { python -c 'import sys; print(sys.argv)' $(head -n1) }
ls | { python -c 'import sys; print(sys.argv); print(input())' $(head -n1) }
seq 1 10000 | { head -n1; head -n2; }
$(printf %cc%co e h) hello, world