回答:
次のifnotempty
関数は、引数として渡されたコマンドに入力をパイプしますが、入力が空の場合は何も行いません。を書くことでパイプsource --foo
に使用します。sink --bar
source --foo | pipe_if_not_empty sink --bar
pipe_if_not_empty () {
head=$(dd bs=1 count=1 2>/dev/null; echo a)
head=${head%a}
if [ "x$head" != x"" ]; then
{ printf %s "$head"; cat; } | "$@"
fi
}
デザインノート:
dd
ません。標準入力で読み取るように指示された1バイト以上を読み取らないことに依存しています。head -c 1
適切な代替品になると思いますdd bs=1 count=1 2>/dev/null
。head -n 1
ためhead
、適切ではありません。パイプから読み取るため、余分なバイトが失われます。read -r head
read -r -n 1 head
最初の文字が改行の場合head
は空の文字列に設定され、空の入力と空行で始まる入力を区別することができないため、ここでも適切ではありません。head=$(head -c 1)
最初の文字が改行の場合、コマンド置換により最終改行が削除され、空の入力と空白行で始まる入力を区別できなくなるため、単に書くことはできません。cat
によって</dev/stdin
微視的なパフォーマンスの向上のために。中間データ全体をメモリに保存することを気にしない場合は、の非常に簡単な実装を次に示しpipe_if_not_empty
ます。
pipe_if_not_empty () {
input=$(cat; echo a);
if [ "x$input" != x"a" ]; then
{ printf %s "${input%a}"; } | "$@"
fi
}
以下は、次の点で若干単純な実装です。
繰り返しますが、データ全体がメモリに保存されます。
pipe_if_not_empty () {
input=$(cat);
if [ "x$input" != x"" ]; then
{ printf '%s\n' "${input}"; } | "$@"
fi
}
これはあなたのために働くはずです
$ --a function-- | [ xargs -r ] --another function--
例
$ echo -e "\n\n" | xargs -r ls
$ # No output. ls did not run.
$ echo -e "\n\n1" | xargs -r ls
ls: cannot access 1: No such file or directory
それは簡単ですが、あなたのために働くはずです。「関数」が空の文字列または改行をパイプラインに送信する場合、xargs -rは「別の関数」への通過を防ぎます。
xargsのリファレンス:http ://www.oreillynet.com/linux/cmd/cmd.csp ? path = x/xargs
-r, --no-run-if-empty
Do not run command if standard input contains only blanks.
ifne(1)から moreutilsは、まさにその作業を行います。Moreutilsは、少なくともDebianとUbuntuで、おそらく他のディストリビューションでもパッケージとして利用できます。
以下の関数は最初のバイトを読み込もうとし、成功した場合はそのバイトをエコーし、残りをcatsします。効率的で、100%ポータブルでなければなりません。
if_read() {
IFS="" read -rN 1 BYTE && { echo -nE "$BYTE"; cat; } | "$@";
}
テストケース:
$ echo -n | if_read wc -c
$ echo | if_read wc -c
1
$ echo -en "\nX" | if_read wc -c
2
$
echo -en "\nX" | pipe_if_not_empty mail -s "Subject line here" foo@bar.com
。これは、と思うline
と、here
いない対象にトークン、電子メールの両方の受信者です。私は"
それを機能させるために対象の周囲から逃げなければなりません。ただし、pipe_if_not_empty
受け入れられた回答からの機能は、何もエスケープしなくても機能します。
少なくともこのような何かが機能します:
yourcommand | if [ $(wc -c) -gt "0" ]; then yourothercommand; fi
上記では改行やその他の特殊文字が出力と見なされるため、そのifステートメントに渡された空の行は出力と見なされることに注意してください。通常、出力が1バイトよりも大きい場合は、-gt制限を上げます。
yourothercommand
の出力は表示されませんyourcommand
。
代わりにsender | receiver
:
tester () { local a=$(</dev/stdin); if [[ $a ]]; then printf '%s\n' "$a" | receiver; fi; }
sender | tester
または、Gillesの回答のように、受信側プログラムを引数として受け入れるように変更することにより、より一般的な目的にすることができます。
tester () { local a=$(</dev/stdin); if [[ $a ]]; then printf '%s\n' "$a" | "$@"; fi; }
sender | tester receiver