Konvertieren Sie Zeilenumbrüche in durch Nullen getrennte Zeilen, wenn Sie tail verwenden

20

Wie kann ich die Ausgabe von ändern tail, um nullterminierte Zeilen anstelle von Zeilenumbrüchen zu verwenden?

Meine Frage ist ähnlich wie die folgende: Wie mache ich "head" und "tail" bei null-getrennten Eingaben in bash? , aber unterscheidet sich darin, dass ich etwas machen möchte wie:

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

Ich benutze es nicht findund kann es auch nicht verwenden-print0

All dies soll den Fehler vermeiden, der in xargs auftritt:

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

Antworten:

26

Wenn du die letzten 10 Zeilen haben willst:

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

Aber mit GNU xargskönnen Sie den Begrenzer auch auf newline setzen mit:

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

( -0ist die Abkürzung für -d '\0').

Portabel kann man auch einfach jedem Charakter entkommen:

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

Oder zitiere jede Zeile:

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

Wenn Sie die letzten 10 NUL-getrennten Datensätze von myFile.txt(aber das wäre dann keine Textdatei) möchten, müssen Sie die in konvertieren \n, \0bevor Sie aufrufen, tailwas bedeuten würde, dass die Datei vollständig gelesen werden muss:

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

Bearbeiten (da Sie das geändert , tailum tail -fin Ihrer Frage):

Der letzte oben ergibt offensichtlich keinen Sinn tail -f.

Das xargs -d '\n'eine wird funktionieren, bei den anderen tritt jedoch ein Pufferungsproblem auf. Im:

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

trpuffert seine Ausgabe, wenn es nicht zu einem Terminal geht (hier eine Pipe). IE wird es nichts schreiben, bis es einen Puffer voll (so etwas wie 8 kB) von Daten zum Schreiben angesammelt hat. Welche Mittel myCmdwerden in Chargen aufgerufen.

Auf einem GNU- oder FreeBSD-System können Sie das Pufferverhalten von trmit dem stdbufBefehl ändern :

tail -f myFile.txt | stdbuf -o0 tr '\n' '\0' |
  xargs -r0i myCmd {} arg1 arg2
Stéphane Chazelas
quelle
Eigentlich wollte ich die Option -f für tail verwenden, die fortlaufend Zeilen druckt, wenn sie eingehen. Ich dachte nicht, dass dies wichtig wäre, aber anscheinend ist es so. Mit der Option -f funktioniert Ihre Lösung nicht.
Lars
Das tail -f myFile.txt | xargs -r0i -d '\n' myCmd "{}" "||" "||"scheint zu funktionieren! Vielen Dank.
Lars
@ Lars, sorry, die -iOption akzeptiert ein optionales Argument, -i0würde also nicht funktionieren. Sie sollten alle mit tail -fAusnahme des letzten arbeiten, aber achten Sie darauf, dass es aufgrund der Pufferung eine Verzögerung geben wird, bevor xargsdie Eingabe von erfolgt tr. Sie können dies ändern, indem Sie stdbuf -o0 tr '\n' '\0'anstelle von ausführen tr '\n' '\0'.
Stéphane Chazelas