Letakkan teks di depan setiap baris baru yang dicetak oleh program untuk stdout

9

Jadi saya ingin melakukan beberapa logging dan karenanya, ingin meletakkan tanggal di depan output skrip bash. Masalahnya adalah bahwa ini memiliki beberapa jalur output. Saya hanya bisa meletakkan tanggal sebelum seluruh output. Tapi kemudian saya memiliki garis tanpa tanggal di log. Tentu saja saya dapat berasumsi bahwa tanggal dari baris di atas sama, tetapi saya berharap ada solusinya. Terima kasih sebelumnya!

Ini skrip saya yang memanggil skrip lain:

#!/bin/sh
echo $(date "+%F %T") : starting script
echo $(date "+%F %T") : $(./script.sh)
echo $(date "+%F %T") :script ended

Ini hasilnya:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
second line of output
2012-07-26 15:35:17 : script ended

Dan itulah yang ingin saya miliki:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
2012-07-26 15:35:15 : second line of output
2012-07-26 15:35:17 : script ended
tzippy
sumber
Saya kira Anda tidak bisa mengubah naskah kedua saja?
jmetz
Nah, sayangnya tidak. Itu sebabnya saya datang ke sini.
tzippy

Jawaban:

9

Menurut pertanyaan serupa pada Stack Overflow , ada 2 pilihan bagus.

awk ( Jawab )

<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'

annotate ( Jawab )

annotate adalah skrip bash kecil, yang dapat langsung diperoleh melalui tautan yang disediakan di sini, atau, pada sistem berbasis Debian, melalui paket devscripts(dalam bentuk annotate-output).

Oliver Salzburg
sumber
3

Saya pikir Anda dapat menggunakan awk untuk ini:

./script.sh | awk '{ print strftime()" : "$0; }'

(lihat http://www.gnu.org/software/gawk/manual/html_node/Time-Functions.html untuk memformat tanggal yang dikembalikan oleh strftime ())

Flinth
sumber
2
awk: calling undefined function strftime- apakah ini khusus untuk gawk?
Daniel Beck
Sekarang Anda menyebutkannya, ya sepertinya: /
Flinth
2

Kamu bisa menggunakan awk

./script.sh | awk '{ print d,$1}' "d=$(date "+%F %T")"

awkmengambil aliran input dan memodifikasi outputnya. Skrip ini mengatakan "cetak d diikuti oleh keluaran asli", lalu isi ddengan tanggal.

Paul
sumber
1
Tidakkah ini mengevaluasi dateekspresi hanya sekali juga, sehingga semua garis seperti itu mencetak waktu yang sama?
Daniel Beck
@DanielBeck Ya itu - saya berasumsi itu mengambil tanggal setiap kali tetapi baru saja menyelesaikan tes saya cukup cepat
Paul
1

Ini akan mencetak tanggal dan waktu saat ini sebelum setiap baris output ./script.sh:

set -f
./script.sh | while read -r LINE; do echo $(date "+%F %T") : "$LINE"; done
set +f

Bagaimana itu bekerja

  • set -fmematikan ekspansi bash (atau echo *tidak mau mencetak tanda bintang yang sebenarnya).

  • while read -r LINE; do ... donemenyimpan satu baris output dalam variabel $LINEdan dijalankan ..., sampai semua baris diproses.

  • echo $ (tanggal "+% F% T"): "$ LINE" mencetak baris dengan waktu dan tanggal saat ini.

  • set +f mengaktifkan ekspansi bash kembali, sehingga tidak akan mengganggu sisa skrip bash Anda.

Dennis
sumber
Itu akan dievaluasi hanya sekali, jadi setiap sedmenyisipkan tanggal yang sama, dari sesaat sebelum memulai skrip kedua. Sepertinya bukan yang diinginkan pengguna ...
Daniel Beck
Saya pikir upaya ini juga tidak akan berhasil. AFAIK, seluruh subshell akan dievaluasi sepenuhnya terlebih dahulu, kemudian loop dilalui. Jadi sekarang waktunya dari setelah eksekusi.
Daniel Beck
Contoh Anda tidak berfungsi, karena Anda hanya menunda output, bukan eksekusi ls. Coba saja skrip Anda dengan yang berikut ini script.sh: #!/bin/bash(baris baru)echo 1 ; sleep 1 ; echo 2 ; sleep 2 ; echo 3 ; sleep 3 ; echo 4
Daniel Beck
Gunakan readdengan whileloop, bukan untuk loop.
chepner
@ chepner: Ide bagus.
Dennis