1

コマンドのリダイレクト/再利用を理解するのに苦労しています...

出力を組み合わせるための<(...) <(...)方法論と手法があることを理解しています。しかし、違いが何であるかを完全には理解$( ... && ... )していません(新しいシェル内にダンプされ、dirをジャンプして、エクスポートしていない変数を失う可能性があることを認識していますが、それがどのように影響するかはわかりません一般的なリダイレクトスキーム)と、次の例と手順をざっと読んだ後、1​​対多のリダイレクトを行う方法についてはまだかなり混乱しています:Advanced Bash Scripting Guide 1 Advanced Bash Scripting Guide 2(...)


私自身がそれをいじってみたところ、ほとんどの場合「あいまいなリダイレクト」エラーが発生しました。

たとえば、以下の擬似コードで指定されたワンライナーを実行したいとします。

    CMD 1 && CMD 2 && CMD 3 --> (1)  
    CMD 4 (1) --> (2)
    CMD 5 (1) --> CMD 6 --> (3)
    CMD 7 (2) && CMD 8 (3) --> (4)
    CMD 9 (2) --> (5)
    CMD 10 (2) (3) -->(6)
    VAR= echo (4) && echo (5) && echo (6)

またはプロセス図として

CMD 1 +CMD 2 && CMD 3 
    |\
    | ---> CMD 5 ------> CMD 6-----\
    V                     /         V
    CMD 4 ----------------u--------> CMD 10
     | \                  V           /
     |   -------->CMD 7 + CMD 8      /
     V             |                /
    CMD 9          |               /
      \            |              /
       \           V             /
        --------> VAR <----------

出力が-->;として指定されている場合。別の操作で再利用するためのストレージは、-->(#);によって与えられます。と組み合わせ操作はによって与えられ&&ます。

私は現在、冗長なコードなしでこれを1行で行う方法がわかりません。

強力なワンライナーを作成できるように、コマンドリダイレクトを本当にマスターしたいと思います。

うまくいけば、それで十分です...必要に応じて、コマンドの概念実証の例を思いつくことができますが、擬似コードでアイデアが得られるはずです。

4

3 に答える 3

2

この投稿には、あなたの問題に対するある種の答えの始まりがあります 。Unix(またはWindows)で(できれば名前のない)パイプを使用して、1つのプロセスのstdoutを複数のプロセスに送信するにはどうすればよいですか?

teeと>(コマンド)を使用します。しかし、あなたの例はかなり洗練されており、コマンドを組み合わせるだけで、一時的なストレージ(varまたはfile)がない1行のソリューションを想像するのは難しいです(Unixの方法です!)。

つまり、複数のコマンドを順番に起動することに同意した場合、それは簡単かもしれません(ただし、もはやワンライナーではなくなります)...

より複雑な言語(Pythonなど)でこの種の式を書くことでさえ、複雑になります。

于 2012-03-14T08:26:27.540 に答える
2

あなたのコメントへの返信:

sort <(cd $CURR_DIR && find . -type f -ctime $FTIME) \ 
    <(cd $CURR_DIR && find . -type f -atime $FTIME) \ 
    <(cd $CURR_DIR && find . -type f -mtime $FTIME) | uniq

次のように書くことができます(私はより明確だと思います)

(find . -type f -ctime $FTIME && find . -type f -atime $FTIME \
    && find . -type f -mtime $FTIME) | sort | uniq

出力として「a」または「z」を生成する3つのプログラムがあるとします。ソートされた出力と、1つのライナーとしての一意の出力を含む文字列を生成します。

mkfifo named_pipe{1,2,3}; (echo z ; echo a ; echo z) > named_pipe1 & \
    tee < named_pipe1 >(sort > named_pipe2) | sort | uniq > named_pipe3 & \
    output=$(echo sorted `cat named_pipe2`; echo unique `cat named_pipe3`); \
    rm named_pipe{1,2,3}

生産するsorted a z z unique a z

このソリューションについて気付くかもしれないことの1つは、コマンドの各グループが独自の行を持つように分割されていることです。私がここで得ているのは、1つのライナーがかっこいいということだと思いますが、多くの場合、透明度の方が優れています。

これがどのように機能するかによるメカニズムは、ティーと名前付きパイプと呼ばれるプログラムの使用です。名前付きパイプは、匿名パイプとまったく同じです。cat words.txt | gzipただし、ファイルシステムから参照できる場合を除きます(ただし、実際のデータはファイルシステムに書き込まれません)。名前付きパイプへの書き込みは、別のプロセスが名前付きパイプから読み取るまでブロックされることに注意してください。私はここでパイプを使用することに満足しているので、パイプの使用方法を感じることができます。

他の人が指摘しているように、ティーは入力を複数の出力に複製できます。

于 2012-03-14T10:11:09.080 に答える
1

解決すべきいくつかの異なる問題があります。

  1. 他のいくつかのコマンドの入力として必要な出力が1つあります。これはで解決できますtee >(cmd1) | cmd2。この回答を参照してください:Unix(またはWindows)で(できれば名前のない)パイプを使用して、1つのプロセスのstdoutを複数のプロセスに送信するにはどうすればよいですか?

    別の方法は、ファイルを作成することです。最終的なスクリプトをデバッグできるので、私は通常ファイルアプローチを好みます。混乱を避けるために、削除する一時的な作業ディレクトリを作成しますtrap "..." EXIT

  2. 1つのコマンドへの入力として、複数のコマンドの出力を組み合わせる必要があります。ここでサブシェルを使用( CMD 1 ; CMD 2 ) | CMD 3します。1と2の出力を3の入力として結合します。

  3. 上記の2つを組み合わせる必要があります。追加のファイル記述子を作成できますが、それぞれを読み取ることができるのは1回だけです。catそれらを組み合わせてteeコピーを作成するために使用します。

これはすべて可能であるはずですが、欠点があります。何かが機能しないか、うまくいかない場合、バグを見つけることができなくなります。

したがって、作業ディレクトリを作成し、ファイルを使用します。これをに入れる/tmpと、データはディスクに書き込まれません(最近のLinuxシステムで/tmpはRAMディスクです)。大量のデータがあり、スクリプトを維持できる場合を除いて、これはパイプのように動作します。

于 2012-03-14T09:06:33.033 に答える