Converti le nuove righe in delimitate da null quando si utilizza tail


20

Come posso modificare l'output tailper utilizzare le righe con terminazione null anziché le newline?

La mia domanda è simile a questa: come fare `head` e` tail` su input delimitati da null in bash? , ma differisce dal fatto che voglio fare qualcosa del tipo:

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

Non sto usando find, e quindi non posso usare-print0

Tutto ciò per evitare l'errore che si verifica in xargs:

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

Risposte:


26

Se vuoi le ultime 10 righe:

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

Ma con GNU xargs, puoi anche impostare il delimitatore su newline con:

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

( -0è l'abbreviazione di -d '\0').

Portabilmente, puoi anche semplicemente sfuggire a ogni personaggio:

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

Oppure cita ogni riga:

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

Se desideri gli ultimi 10 record delimitati da NUL di myFile.txt(ma non si tratterebbe di un file di testo), dovresti convertirlo \nin \0prima di chiamare, il tailche significa che il file dovrà essere letto completamente:

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

Modifica (poiché hai modificato il tailin tail -fnella tua domanda):

L'ultimo sopra ovviamente non ha senso tail -f.

L' xargs -d '\n'uno funzionerà, ma per gli altri avrai un problema di buffering. Nel:

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

trbuffer il suo output quando non va a un terminale (qui, una pipe). IE, non scriverà nulla fino a quando non avrà accumulato un buffer pieno (qualcosa come 8 kB) di dati da scrivere. Il che significa myCmdche verrà chiamato in batch.

Su un sistema GNU o FreeBSD, puoi modificare il comportamento del buffering trcon il stdbufcomando:

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

In realtà intendevo usare l'opzione -f sulla coda, che stampa continuamente le linee man mano che entrano. Non pensavo che questo avrebbe avuto importanza, ma a quanto pare. Con l'opzione -f la tua soluzione non funziona.
Lars,

La tail -f myFile.txt | xargs -r0i -d '\n' myCmd "{}" "||" "||"sembra funzionare! Grazie.
Lars,

@Lars, mi dispiace, l' -iopzione accetta un argomento facoltativo, quindi -i0non funzionerebbe. Dovrebbero funzionare tutti tail -ftranne l'ultimo, ma attenzione che a causa del buffering, ci sarà un ritardo prima che xargsottenga il suo input tr. Puoi cambiarlo eseguendo stdbuf -o0 tr '\n' '\0'invece di tr '\n' '\0'.
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.