Convierta nuevas líneas en delimitadas por nulos cuando use tail

20

¿Cómo puedo cambiar la salida tailpara usar líneas terminadas en nulo en lugar de líneas nuevas?

Mi pregunta es similar a esta: ¿Cómo hacer `head` y` tail` en entradas delimitadas por nulos en bash? , pero difiere en que quiero hacer algo como:

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

No estoy usando find, por lo que no puedo usar-print0

Todo esto es para evitar el error que ocurre en xargs:

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

Respuestas:

26

Si quieres esas últimas 10 líneas:

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

Pero con GNU xargs, también puede establecer el delimitador en nueva línea con:

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

( -0es la abreviatura de -d '\0').

Portablemente, también puedes escapar de cada personaje:

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

O cita cada línea:

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

Si desea los 10 últimos registros delimitados por NUL de myFile.txt(pero eso no sería un archivo de texto), tendría que convertir el archivo \na \0antes de llamar, taillo que significaría que el archivo tendrá que leerse completamente:

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

Editar (ya que cambiaste taila tail -fen tu pregunta):

El último de arriba obviamente no tiene sentido tail -f.

El xargs -d '\n'uno funcionará, pero para los otros, tendrá un problema de almacenamiento en búfer. En:

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

tralmacena su salida cuando no va a una terminal (aquí, una tubería). Es decir, no escribirá nada hasta que haya acumulado un búfer lleno (algo así como 8 kB) de datos para escribir. Lo myCmdque se llamará en lotes.

En un sistema GNU o FreeBSD, puede alterar el comportamiento de almacenamiento en búfer trcon el stdbufcomando:

tail -f myFile.txt | stdbuf -o0 tr '\n' '\0' |
  xargs -r0i myCmd {} arg1 arg2
Stéphane Chazelas
fuente
En realidad, tenía la intención de usar la opción -f en la cola, que imprime continuamente líneas a medida que entran. No pensé que esto importara, pero aparentemente sí. Con la opción -f su solución no funciona.
Lars
El tail -f myFile.txt | xargs -r0i -d '\n' myCmd "{}" "||" "||"parece funcionar! Gracias.
Lars
@Lars, lo siento, la -iopción tiene un argumento opcional, por -i0lo que no funcionaría. Todos deberían funcionar, tail -fexcepto el último, pero tenga en cuenta que debido al almacenamiento en búfer, habrá un retraso antes de xargsobtener su entrada tr. Puede cambiar eso ejecutando en stdbuf -o0 tr '\n' '\0'lugar de tr '\n' '\0'.
Stéphane Chazelas