パイプが空であることを確認し、空である場合は、データに対してコマンドを実行するにはどうすればよいですか?

パイプが空であることを確認し、空である場合は、データに対してコマンドを実行するにはどうすればよいですか?

私はbashスクリプトに行をパイプし、プログラムにデータを供給する前にパイプにデータがあることを確認したいと思います。

検索してみましたが、test -t 0ここではうまくいきません。常に false を返します。では、パイプラインにデータがあるかどうかを確認できますか?

例:

echo "string" | [ -t 0 ] && echo "empty" || echo "fill"

出力:fill

echo "string" | tail -n+2 | [ -t 0 ] && echo "empty" || echo "fill"

出力:fill

同じではない上記のパイプラインが出力を生成するかどうかをテストする標準/標準方法は何ですか?入力をプログラムに渡すには、入力を保存する必要があります。これをまとめるあるプロセスから別のプロセスに出力をパイプするにはどうすればよいですか?ただし、最初のプロセスに出力がある場合にのみ実行しますか?電子メールの送信に焦点を当てます。

答え1

一般的なシェルユーティリティを使用してパイプの内容を表示する方法はなく、パイプから文字を読み書きできる移植可能な方法もありません。パイプにデータがあるかどうかを知る唯一の方法は、バイトを読み取ることです。その後、バイトを宛先に送信する必要があります。

したがって、次のようにしてください。ファイルの終わりが検出された場合は入力が空のときに必要な操作を行い、バイトを読み取ると入力が空でないときにフォークします。必要な作業はパイプです。バイトをここに入れて、残りのデータをパイプします。

first_byte=$(dd bs=1 count=1 2>/dev/null | od -t o1 -A n | tr -dc 0-7)
if [ -z "$first_byte" ]; then
  # stuff to do if the input is empty
else
  {
    printf "\\$first_byte"
    cat
  } | {
    # stuff to do if the input is not empty
  }      
fi

これifneユーティリティは以下から来ます。Joey Hessのmoreutils入力が空でない場合、コマンドが実行されます。通常、デフォルトではインストールされませんが、ほとんどのUNIXバリアントで簡単に動作または構築されます。入力が空の場合、ifne操作は実行されず、正常なコマンド実行と区別できない状態0が返されます。入力が空のときに何をするには、コマンドがゼロを返さないように準備する必要があります。これは、成功事例に区別可能なエラー状態を返すことによって行うことができます。

ifne sh -c 'do_stuff_with_input && exit 254'
case $? in
  0) echo empty;;
  254) echo success;;
  *) echo failure;;
esac

test -t 0これは、標準入力が端末であるかどうかをテストすることとは関係ありません。入力が可能かどうかはまったく教えてくれません。

254はここでランダムに選択され、255は特定のコマンドを実行するのが比較的一般的であるためexit(-1)(通常は255になる)ことを避けます。$?-exec(-2)

答え2

簡単な解決策はifneコマンドを使用することです(入力が空でない場合)。一部のディストリビューションではデフォルトではインストールされません。これはほとんどのディストリビューションのソフトウェアパッケージの一部ですmoreutils

ifne標準入力が空でない場合にのみ、指定されたコマンドを実行してください。

標準入力が空でない場合は、ifne与えられたコマンドに渡されます。

答え3

stdin(0) のファイル記述子が開いているか閉じているか確認してください。

[ ! -t 0 ] && echo "stdin has data" || echo "stdin is empty"

答え4

古い質問ですが、私のような人が発生した場合に備えて、私の解決策は時間制限を置いて読むことでした。

while read -t 5 line; do
    echo "$line"
done

空の場合、stdin5秒後に返されます。それ以外の場合は、すべての入力を読み取り、必要に応じて処理できます。

サポートされている場合は、-t入力を使用してデータを読み取る前に入力をテストできます-t0。 (-u0awslinuxではSTDINが必要で、UbuntuではSTDINを想定しているので、STDINも指定してください。)

if [ $(read -u0 -t0) ]; then ....

その後、正常に読み始めることができます。

からhelp read

TIMEOUT が 0 の場合、読み取りはデータの読み取りを試みずにすぐに返され、指定されたファイル記述子から入力が可能な場合にのみ成功を返します。

関連情報