2012-02-11 7 views
1

私はループでプリントするスクリプトを持っています。私は、ループが他のすべての時間から最初に異なって印刷されるようにしたい(つまり、何かが全く印刷されていないと、別の方法で印刷するはずです)。私は、何かがまだ印刷されているかどうか(つまり、stdoutに書き込まれているかどうか)をチェックするのが簡単な方法だと考えています。それを決める方法はありますか?stdoutが書き込まれているかどうかをテストします

変数に書き込んで空であるかどうかをテストすることもできますが、できれば変数を避けたいと思います。

+0

なぜ変数を避けたいですか?コードをより読みやすく保守しやすくします。知覚される費用は何ですか? – Johnsyweb

+0

ループカウンタをテストするだけではどうですか?私はあなたが言うことを知っている**私は変数**を避けたいですが、なぜですか? 'tmpfileへのリダイレクト'は良い解決策ですが、あなたは変数よりもずっと多くを追加しています...単純な 'declare -i cnt; while [あなたのループ]。 #stuffを実行します。 if [cnt -eq 0];それからprintf "a";そうでなければprintf "b"; fi; ((cnt ++)); doneはかなり短く、IO時間とオーバーヘッドを追加するtmpfileを避けます。 –

答えて

1

私はあなたが必要とすることをすると思います。 # THE SCRIPT ITSELF# END間あなたがecho何か場合は、THE FOLLOWING DATA HAS BEEN WRITTEN TO STDOUTは...他にSTDOUT HAS NOT BEEN TOUCHED印刷されます

 
#!/bin/bash 

readonly TMP=$(mktemp /tmp/test_XXXXXX) 

exec 3<> "$TMP" # open tmp file as fd 3 
exec 4>&1   # save current value of stdout as fd 4 
exec >&3   # redirect stdout to fd 3 (tmp file) 

# THE SCRIPT ITSELF 

echo Hello World 

# END 

exec >&4   # restore save stdout 
exec 3>&-   # close tmp file 

TMP_SIZE=$(stat -f %z "$TMP") 
if [ $TMP_SIZE -gt 0 ]; then 
    echo "THE FOLLOWING DATA HAS BEEN WRITTEN TO STDOUT" 
    echo 
    cat "$TMP" 
else 
    echo "STDOUT HAS NOT BEEN TOUCHED" 
fi 

rm "$TMP" 

だから、スクリプトの出力があるよう:

 

THE FOLLOWING DATA HAS BEEN WRITTEN TO STDOUT 

Hello World 

、あなたはecho Hello World行を削除する場合:

 
STDOUT HAS NOT BEEN TOUCHED 

スクリプトを実行している間に実際にテストしたい場合は、その、あまりにも

 
#!/bin/bash 

#FIRST ELSE 
function echo_fl() { 
    TMP_SIZE=$(stat -f %z "$TMP") 
    if [ $TMP_SIZE -gt 0 ]; then 
     echo $2 
    else 
     echo $1 
    fi 
} 

TMP=$(mktemp /tmp/test_XXXXXX) 

exec 3 "$TMP" # open tmp file as fd 3 
exec 4>&1   # save current value of stdout as fd 4 
exec >&3   # redirect stdout to fd 3 (tmp file) 

# THE SCRIPT ITSELF 

for f in fst snd trd; do 
    echo_fl "$(echo $f | tr a-z A-Z)" "$f" 
done 

# END 

exec >&4   # restore save stdout 
exec 3>&-   # close tmp file 

TMP_SIZE=$(stat -f %z "$TMP") 
if [ $TMP_SIZE -gt 0 ]; then 
    echo "THE FOLLOWING DATA HAS BEEN WRITTEN TO STDOUT" 
    echo 
    cat "$TMP" 
else 
    echo "STDOUT HAS NOT BEEN TOUCHED" 
fi 

rm "$TMP" 

:-)出力は次のようになります。

 
THE FOLLOWING DATA HAS BEEN WRITTEN TO STDOUT 

FST 
snd 
trd 

あなたが見ることができるように:のみ最初の行(FSTは)上のキャップを持っています。それはあなたのためにecho_fl関数が何をしているのかです:出力の最初の行で、最初の引数をエコーし​​た場合、2番目の引数:-)をエコーし​​ます。

+0

これはまだ変数として 'TMP'を作成しますが、かなりクールです。しかし、私はそれを回避することができるかもしれません。私は何をしようとしている変数を使うのがずっと簡単だと思います。 –

+0

ええ、それでも変数 'TMP'が作成されますが、他のプログラムによって出力が行われていても動作します。 'for fst snd trd ...'ループの前に 'cat/etc/fstab'を置いたとすると' fst'は大文字で表示されます!変数の問題は何ですか? –

+0

ところで、 'TMP'は変数よりも定数です。私はそれを 'readonly'としてマーク(編集)しました。 –

1

ここで何をしようとしているのか、スクリプトがstdoutに印刷している場合は、それはperlへあなたは可能性があり、単純にパイプ:

yourcommand | perl -pe 'if ($. == 1) { print "First line is: $_" }' 

それはすべてあなたがしようとしている変更の種類によって異なります。

0

-fオプションは%zで使用できません。 TMP_SIZE=$(stat -f %z "$TMP")行は、長い文字列を生成します。長い文字列は、if [ $TMP_SIZE -gt 0 ]でテストに失敗します。