zsh:コマンド置換は、親項目から標準入力を継承しません。

zsh:コマンド置換は、親項目から標準入力を継承しません。

次のコマンドを検討してください。

seq 5 | grep $(tail -n1) <(seq 9)

zsh1で実行すると:

tail: error reading 'standard input': Input/output error

で同じタスクを実行すると、bash次のように出力されます。

5

いいえコメントに記載されているように、コマンド置換は親エントリから継承さ$(tail -n1)れます。stdinしかし、なぜこのようなことは起こりませんかzsh
これがzsh唯一のものですか、それとも他のシェルもこれを行いますか?どこに記録されていますか?


さて、次のコマンドで同じコマンドを実行するとzsh -c

zsh -c 'seq 5 | grep $(tail -n1) <(seq 9)'

同じエラーメッセージを印刷する代わりに停止してtail -n1ユーザー入力を待つので、次のように入力します。

19
2
4

Ctrl次に+を押すとD印刷されます。

4

ここで何が起こっているのでしょうか?


1: 重要ならこれはzsh 5.3.1on です。archlinux

答え1

あなたは知っているでしょうbash/ksh

echo foo | echo "$(cat)"

出力foo

<<< foo echo "$(cat)"

いいえ。

最初のケースでは、標準入力はパイプからリダイレクトされ、最後に$(cat)実行されるサブプロセスから解放されます。echo

2番目の場合は、$(cat)リダイレクトする前に拡張してください。

パイプとリダイレクトは異なります。パイプラインには一部が含まれています。リダイレクトコマンドを並列に実行することも可能です。これは、各パイプラインコンポーネントの内部リダイレクトの前に発生します。

存在するzsh

$ sleep 1 | ps -jfH $(ps -fH >&2)
UID        PID  PPID  C STIME TTY          TIME CMD
chazelas  2495  2494  0 20:59 pts/1    00:00:00 /bin/zsh
chazelas 31201  2495  0 21:20 pts/1    00:00:00   sleep 1
chazelas 31202  2495  0 21:20 pts/1    00:00:00   ps -fH
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
chazelas  2495  2494  2495  2495  0 20:59 pts/1    00:00:00 /bin/zsh
chazelas 31201  2495 31201  2495  0 21:20 pts/1    00:00:00   sleep 1
chazelas 31203  2495 31201  2495  0 21:20 pts/1    00:00:00   ps -jfH

今回は、コマンド置換が親シェルによって拡張されたことがわかります。

覚えておくべきことの1つは、パイプは特にオプション(デフォルトで有効になっている)zshに関してリダイレクトのように扱われることです。mult_ios

これを行うとき:

echo foo > file | tr o e

foofileとに移動しますtr

存在する:

uname | cat < /etc/issue

cat入力される出力合計unameの内容です/etc/issue。したがって、zshパイプラインへのパイプラインへのリダイレクトは同じ段階で発生する必要があります。拡張後に使用することをお勧めします。<>

とにかく、いつでも次のことができます。

echo foo | { echo "$(cat)"; }

inzshbash/kshいつものように:

{ echo "$(cat)"; } <<< foo

そしてbashzsh


理由は次のとおりです。

tail: error reading 'standard input': Input/output error

間違い。対話型シェルでは、コマンド置換は親プロセスで実行されるため、端末のフォアグラウンドプロセスグループでは実行されません。

tail親シェルのプロセスグループで実行されます。シェルがセッションリーダーの場合、孤児プロセスグループしたがって、tailttyデバイスから読み取ろうとすると、EIOが失敗します。

zsh会議の主催者ではない場合。たとえば、別のシェルから起動すると、zshプロセスグループはSIGTTINを受け取ります。デフォルトのシェルプロセスはこれを無視しますが、tail最終的に中断されます。

関連情報