Mencari yang seperti ini? Ada ide?
cmd | prepend "[ERRORS] "
[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc
Mencari yang seperti ini? Ada ide?
cmd | prepend "[ERRORS] "
[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc
Jawaban:
cmd | while read line; do echo "[ERROR] $line"; done
memiliki keunggulan hanya menggunakan bash builtin sehingga lebih sedikit proses akan dibuat / dihancurkan sehingga harus menjadi sentuhan lebih cepat daripada awk atau sed.
@ tzrik menunjukkan bahwa itu mungkin juga membuat fungsi bash yang bagus. Mendefinisikannya seperti:
function prepend() { while read line; do echo "${1}${line}"; done; }
akan memungkinkannya digunakan seperti:
cmd | prepend "[ERROR] "
sed
) atau bahkan string yang membelah ( awk
) digunakan.)
function prepend() { while read line; do echo "${1}${line}"; done; }
Coba ini:
cmd | awk '{print "[ERROR] " $0}'
Tepuk tangan
awk -vT="[ERROR] " '{ print T $0 }'
atauawk -vT="[ERROR]" '{ print T " " $0 }'
T="[ERROR] " awk '{ print ENVIRON["T"] $0 }'
atauT="[ERROR]" awk '{ print ENVIRON["T"] " " $0 }'
cmd | awk '{print "['$V]' " $0}'
- ini harus dievaluasi sekali pada awal, jadi tidak ada overhead kinerja.
Dengan segala penghargaan kepada @grawity, saya mengirimkan komentarnya sebagai jawaban, karena sepertinya ini jawaban terbaik bagi saya.
sed 's/^/[ERROR] /' cmd
awk
satu-kapal ini cukup bagus, tapi saya pikir bahwa lebih banyak orang yang akrab dengan sed
dari awk
. Skrip bash baik untuk fungsinya, tetapi tampaknya ia menjawab pertanyaan yang tidak ditanyakan.
sed X cmd
membaca cmd
dan tidak menjalankannya. Entah cmd | sed 's/^/[ERROR] /'
atau sed 's/^/[ERROR] /' <(cmd)
atau cmd > >(sed 's/^/[ERROR] /')
. Namun waspadalah terhadap yang terakhir. Bahkan bahwa ini memungkinkan Anda untuk mengakses nilai kembali dari cmd
yang sed
berjalan di latar belakang, sehingga kemungkinan Anda melihat output setelah cmd selesai. Bagus untuk masuk ke file. Dan perhatikan bahwa awk
mungkin lebih cepat dari sed
.
alias lpad="sed 's/^/ /'"
. bukannya ERROR saya memasukkan 4 spasi utama. Sekarang, untuk trik sulap: ls | lpad | pbcopy
akan menambahkan ls output dengan 4 spasi yang menandainya sebagai Penurunan harga untuk kode , yang berarti bahwa Anda menempelkan clipboard ( pbcopy ambil, pada mac) langsung ke StackOverflow atau konteks penurunan harga lainnya. Tidak bisa alias
dengan awk jawaban (pada tanggal 1 try) jadi ini salah satu menang. Solusi sambil membaca juga alias-mampu, tetapi saya menemukan sed ini lebih ekspresif.
Saya membuat repositori GitHub untuk melakukan beberapa tes kecepatan.
Hasilnya adalah:
awk
ini tercepat. sed
sedikit lebih lambat dan perl
tidak lebih lambat dari sed
. Rupanya, semua itu adalah bahasa yang sangat optimal untuk pemrosesan teks.ksh
( shcomp
) dapat menghemat waktu pemrosesan lebih banyak. Sebaliknya, bash
mati lambat dibandingkan dengan ksh
skrip yang dikompilasi .awk
tampaknya tidak sepadan dengan usaha.Sebaliknya python
sangat lambat, tetapi saya belum menguji case yang dikompilasi, karena biasanya bukan apa yang akan Anda lakukan dalam case scripting seperti itu.
Varian berikut diuji:
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] $_"'
Dua varian biner dari salah satu alat saya (meskipun tidak dioptimalkan untuk kecepatan):
./unbuffered.dynamic -cp'[TEST] ' -q ''
./unbuffered.static -cp'[TEST] ' -q ''
Python buffered:
python -uSc 'import sys
for line in sys.stdin: print "[TEST]",line,'
Dan Python tidak ditemukan:
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 }'
untuk mengeluarkan stempel waktu
Saya menginginkan solusi yang menangani stdout dan stderr, jadi saya menulis prepend.sh
dan meletakkannya di jalur saya:
#!/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)
Sekarang saya bisa menjalankan prepend.sh "[ERROR]" cmd ...
, untuk menambahkan "[KESALAHAN]" ke output cmd
, dan masih memiliki stderr dan stdout terpisah.
>(
subkulit yang tidak bisa saya selesaikan. Tampaknya skrip itu selesai, dan hasilnya tiba ke terminal setelah prompt kembali yang agak berantakan. Saya akhirnya datang dengan jawaban di sini stackoverflow.com/a/25948606/409638