Bash 链式命令的stdin和命令替换中的命令

Bash 链式命令的stdin和命令替换中的命令,bash,zsh,Bash,Zsh,让我先介绍我的发现,然后在最后提出我的问题。(1) 仅适用于zsh,并且(2)、(3)同时适用于zsh和bash 1.命令替换标准 第一个打印猫:-:输入/输出错误;而第二个则产生ls的输出 2.管道后的链接命令 第一个命令不能正常工作cat遇到EOF并直接退出。但是第二种形式是有效的:第一行被读入a,而cat得到其余的部分 3.混合标准 在第一行的{}中,命令用于打印cmdline参数;在第二种形式中,该命令还从stdin读取一行 由于input()读取EOF,当第二个表单抛出时,第一个命令可

让我先介绍我的发现,然后在最后提出我的问题。(1) 仅适用于
zsh
,并且(2)、(3)同时适用于
zsh
bash

1.命令替换标准 第一个打印猫:-:输入/输出错误;而第二个则产生
ls
的输出

2.管道后的链接命令 第一个命令不能正常工作
cat
遇到
EOF
并直接退出。但是第二种形式是有效的:第一行被读入
a
,而
cat
得到其余的部分

3.混合标准 在第一行的
{}
中,命令用于打印cmdline参数;在第二种形式中,该命令还从
stdin
读取一行

由于
input()
读取
EOF
,当第二个表单抛出时,第一个命令可以成功运行

我的问题是:
  • (如第1节所述)带
    {}
    的表单与不带
    {}
    的表单有什么区别
  • (如第2节所述,
    头部
    cat
    是否可以按顺序读取相同的
    stdin
    ?第二种形式如何成功而第一种形式失败
  • (如第3节所述)在命令替换中,命令的
    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:in
    production|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:in
    production|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