bashリダイレクトを学んでいます。以下のコードがls | grep foo | grep bar
。
#!/bin/bash
{
{
ls | grep foo
} 2>&1 1>&4 | grep bar
} 4>&1
これはfooと一致しますが、fooとbarとは一致しません。2>&1
私はfd 1のパイプがfd 2にコピーされ、fd 1をstdoutにリセットするのでこれがうまくいくと思います。
中かっこ(コンテキスト)を維持しながらこのコードを変更できますか?削除すると2>&1 1>&4
期待どおりに動作します。しかし、私は学びたい。
パイプの左側ではstdoutだけが必要だと思うので、パイプをfd 2にコピーしても、パイプの左側でfd 1だけを探します。
引用:https://wiki.bash-hackers.org/howto/redirection_tutorial#an_example
上記のリンクには、cmd1のfd 2がcmd3のfd 0を指す図があります。私は私の例を通してこれを確認しようとしています。
答え1
あなたの試み:
{
{
ls | grep foo # goes to stdout (fd 1)
} 2>&1 1>&4 | grep bar # at this level: 2 now points to where fd1 is pointing (stdout), and 1 is *then* directed to the new fd 4 (ie to stdin of the outside curly)
} 4>&1 ## at this shell 'level', a new fd 4 is now pointing to where 1 is pointing: stdout
:したがって、grepバーは{ls | grep foo}のstderrでのみ行われるため、空の標準入力では{ls | grep foo}のstderrが{ls grep foo} grep fooに移動します。 }.ファイル名は表示されません。このファイル名をfd 4に入力してください。
{
{
ls | grep foo
} 2>&1 1>&4
} 4>&1 | grep bar
または
{
{
ls | grep foo
} 2>&1 1>&4 | <&4 grep bar
} 4>&1
比較して...
注:内部コマンドのstderrもstdoutに移動するには、それを2番目の場所にコピーする必要があります。 1>&4 2>&1 [つまり、1 は fd 4 に移動し、2 は 1 の位置に移動します。今指していること、つまりfd 4と]
答え2
私が知る限り、次は本当です。
これ
{
{
ls | grep foo
} 2>&1 1>&4 | grep bar
} 4>&1
等しい
(ls | grep foo 2>&1 1>&4 | grep bar) 4>&1
fd 4が/dev/pts/0で、1>&4のため、fd 1がパイプの代わりに同じ/dev/pts/0を持つようになるため、失敗します。
答え3
リダイレクトを通じてデータをコピーしたいと思いますか?tee
あなたが学んでいる間、私はもう仕事を台無しにしません。
shellcheck
コードの検査にも使用できます。ほとんどのエラーをすばやく見つけるのに役立ちます。