回答:
cmd | while read line; do echo "[ERROR] $line"; done
bashビルトインのみを使用する利点があるため、作成/破棄されるプロセスが少なくなるため、awkやsedよりも速くタッチする必要があります。
@tzrikは、それが素敵なbash関数を作成することもあると指摘しています。次のように定義します:
function prepend() { while read line; do echo "${1}${line}"; done; }
次のように使用できるようになります。
cmd | prepend "[ERROR] "
sed
)または文字列分割(awk
)も使用されていないため、高速になる可能性があります。)
function prepend() { while read line; do echo "${1}${line}"; done; }
これを試して:
cmd | awk '{print "[ERROR] " $0}'
乾杯
awk -vT="[ERROR] " '{ print T $0 }'
またはawk -vT="[ERROR]" '{ print T " " $0 }'
T="[ERROR] " awk '{ print ENVIRON["T"] $0 }'
またはT="[ERROR]" awk '{ print ENVIRON["T"] " " $0 }'
cmd | awk '{print "['$V]' " $0}'
これは開始時に一度評価されるため、パフォーマンスのオーバーヘッドはありません。
@grawityの功績により、彼のコメントを回答として提出しています。
sed 's/^/[ERROR] /' cmd
awk
ワンライナーが素敵十分ですが、私はより多くの人が精通していることを考えるsed
よりawk
。bashスクリプトは何をするのにも適していますが、尋ねられていない質問に答えているようです。
sed X cmd
読み取りcmd
を実行しません。どちらかcmd | sed 's/^/[ERROR] /'
またはsed 's/^/[ERROR] /' <(cmd)
かcmd > >(sed 's/^/[ERROR] /')
。ただし、後者には注意してください。これは、あなたがの戻り値にアクセスすることを可能にしてもいること、それはおそらくあなたが出力を見ているので、バックグラウンドで実行した後、 cmdを完成。ただし、ファイルへのログインには適しています。そして、おそらくより速いことに注意してください。cmd
sed
awk
sed
alias lpad="sed 's/^/ /'"
。エラーの代わりに、先頭に4つのスペースを挿入します。さて、マジックのトリック: ls | lpad | pbcopy
として4つのスペースマーク、それをしてLSの出力を付加しますマークダウンのためのコードを使用すると、(クリップボードを貼り付けることを意味し、pbcopyが直接にStackOverflowまたはその他の値下げコンテキストにMac上で、それをつかみます)。(最初の試行で)awkの答えができなかっalias
たので、これが勝ちです。 しばらく読み取りソリューションは、別名-できますが、私は、これは見つけるのsedより表現。
速度テストを行うためにGitHubリポジトリを作成しました。
結果は次のとおりです。
awk
は最速です。 sed
は少し遅く、より遅くperl
はありませんsed
。どうやら、これらはすべてテキスト処理用に高度に最適化された言語です。ksh
スクリプト(shcomp
)として実行すると、処理時間をさらに節約できます。対照的に、bash
コンパイルされたksh
スクリプトと比較して非常に遅いです。awk
ことは、努力する価値がないと思われます。対照的にpython
、非常に遅いですが、コンパイルされたケースはテストしていません。これは、通常、このようなスクリプトケースで行うことではないからです。
次のバリアントがテストされます。
while read line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST]" $line; done
while read -r line; do echo "[TEST]" "$line"; done
sed 's/^/[TEST] /'
awk '{ print "[TEST] " $0 }'
awk -vT="[TEST] " '{ print T $0 }'
awk -vT="[TEST]" '{ print T " " $0 }'
awk -vT="[TEST]" 'BEGIN { T=T " "; } { print T $0 }'
T="[TEST] " awk '{ print ENVIRON["T"] $0 }'
T="[TEST]" awk '{ print ENVIRON["T"] " " $0 }'
T="[TEST]" awk 'BEGIN { T=ENVIRON["T"] " " } { print T $0 }'
perl -ne 'print "[TEST] $_"'
私のツールの1つの2つのバイナリバリアント(ただし、速度は最適化されていません):
./unbuffered.dynamic -cp'[TEST] ' -q ''
./unbuffered.static -cp'[TEST] ' -q ''
Pythonバッファリング:
python -uSc 'import sys
for line in sys.stdin: print "[TEST]",line,'
そして、バッファなしのPython:
python -uSc 'import sys
while 1:
line = sys.stdin.readline()
if not line: break
print "[TEST]",line,'
awk -v T="[TEST %Y%m%d-%H%M%S] " '{ print strftime(T) $0 }'
出力にタイムスタンプ
stdoutとstderrを処理するソリューションが必要だったので、書きprepend.sh
、それを自分のパスに入れました。
#!/bin/bash
prepend_lines(){
local prepended=$1
while read line; do
echo "$prepended" "$line"
done
}
tag=$1
shift
"$@" > >(prepend_lines "$tag") 2> >(prepend_lines "$tag" 1>&2)
これでprepend.sh "[ERROR]" cmd ...
、を実行して、の出力に「[ERROR]」を追加することができますがcmd
、まだstderrとstdoutは分離されています。
>(
サブシェルでは、解決できなかった何かが進行していました。スクリプトが完了しているように見え、プロンプトが戻った後に出力が端末に到着しているようで、少し面倒でした。最終的にここで答えを