Konversikan baris baru ke batas nol saat menggunakan ekor

20

Bagaimana saya bisa mengubah output dari tailmenggunakan garis nol-dihentikan bukan baris baru?

Pertanyaan saya mirip dengan yang ini: Bagaimana melakukan `head` dan` tail` pada input null-delimited di bash? , tetapi berbeda karena saya ingin melakukan sesuatu seperti:

tail -f myFile.txt | xargs -i0 myCmd {} "arg1" "arg2"

Saya tidak menggunakan find, jadi tidak bisa digunakan-print0

Semua ini untuk menghindari kesalahan yang terjadi di xargs:

xargs: unmatched double quote;
    by default quotes are special to xargs unless you use the -0 option
Lars
sumber

Jawaban:

26

Jika Anda ingin 10 baris terakhir:

tail myFile.txt | tr '\n' '\0' | xargs -r0i myCmd {} arg1 arg2

Tetapi dengan GNU xargs, Anda juga dapat mengatur pembatas ke baris baru dengan:

tail myFile.txt | xargs -ri -d '\n' myCmd {} arg1 arg2

( -0kependekan dari -d '\0').

Dengan mudah, Anda juga dapat melarikan diri dari setiap karakter:

tail myFile.txt | sed 's/./\\&/g' | xargs -I{} myCmd {} arg1 arg2

Atau kutip setiap baris:

tail myFile.txt | sed 's/"/"\\""/g;s/.*/"&"/' | xargs -I{} myCmd {} arg1 arg2

Jika Anda ingin 10 catatan terakhir dibatasi NUL myFile.txt(tapi kemudian itu bukan file teks), Anda harus mengonversikan \nke \0sebelum memanggil tailyang artinya file tersebut harus dibaca sepenuhnya:

tr '\n\0' '\0\n' < myFile.txt |
  tail |
  tr '\n\0' '\0\n' |
  xargs -r0i myCmd {} arg1 arg2

Edit (karena Anda mengubah tailke tail -fdalam pertanyaan Anda):

Yang terakhir di atas jelas tidak masuk akal tail -f.

Yang xargs -d '\n'satu akan bekerja, tetapi untuk yang lain, Anda akan memiliki masalah buffering. Di:

tail -f myFile.txt | tr '\n' '\0' | xargs -r0i myCmd {} arg1 arg2

trbuffer hasilnya ketika tidak pergi ke terminal (di sini, sebuah pipa). IE, itu tidak akan menulis apa pun sampai ia mengumpulkan buffer penuh (seperti 8kiB) data untuk ditulis. Yang artinya myCmdakan dipanggil dalam batch.

Pada sistem GNU atau FreeBSD, Anda dapat mengubah perilaku buffering trdengan stdbufperintah:

tail -f myFile.txt | stdbuf -o0 tr '\n' '\0' |
  xargs -r0i myCmd {} arg1 arg2
Stéphane Chazelas
sumber
Sebenarnya saya bermaksud menggunakan opsi -f pada bagian ekor, yang terus-menerus mencetak garis ketika mereka masuk. Saya tidak berpikir ini masalah, tetapi ternyata itu penting. Dengan opsi -f solusi Anda tidak berfungsi.
Lars
The tail -f myFile.txt | xargs -r0i -d '\n' myCmd "{}" "||" "||"tampaknya bekerja! Terima kasih.
Lars
@ Lars, maaf, -iopsi mengambil argumen opsional, jadi -i0tidak akan berfungsi. Mereka semua harus bekerja dengan tail -fkecuali yang terakhir, tetapi berhati-hatilah karena karena buffering, akan ada penundaan sebelum xargsmendapat input dari tr. Anda dapat mengubahnya dengan menjalankan stdbuf -o0 tr '\n' '\0'alih-alih tr '\n' '\0'.
Stéphane Chazelas