Конвертировать переводы строк в нуль-разделители при использовании хвоста

20

Как я могу изменить вывод, tailчтобы использовать строки с нулевым символом в конце вместо новых?

Мой вопрос похож на этот: как сделать `head` и` tail` для ввода с нулем в bash? , но отличается тем, что я хочу сделать что-то вроде:

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

Я не использую find, и поэтому не могу использовать-print0

Все это для того, чтобы избежать ошибки, возникающей в xargs:

xargs: unmatched double quote;
    by default quotes are special to xargs unless you use the -0 option
Lars
источник

Ответы:

26

Если вы хотите, чтобы последние 10 строк:

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

Но с GNU xargsвы также можете установить разделитель на новую строку с помощью:

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

( -0сокращение от -d '\0').

В частности, вы также можете просто убежать от каждого персонажа:

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

Или процитируйте каждую строку:

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

Если вам нужны 10 последних записей, разделенных NUL myFile.txt(но это не текстовый файл), вам нужно преобразовать в \nзначение \0перед вызовом, tailчто будет означать, что файл нужно будет прочитать полностью:

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

Edit (так как вы изменили , tailчтобы tail -fв вашем вопросе):

Последнее выше, очевидно, не имеет смысла tail -f.

xargs -d '\n'Один будет работать, но и для других, вы будете иметь проблемы буферизации. В:

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

trбуферизует его вывод, когда он не идет к терминалу (здесь, канал). То есть, он не будет ничего писать, пока не накопит полный буфер (что-то вроде 8 кБ) данных для записи. Какие средства myCmdбудут называться партиями.

В системе GNU или FreeBSD вы можете изменить поведение буферизации trс помощью stdbufкоманды:

tail -f myFile.txt | stdbuf -o0 tr '\n' '\0' |
  xargs -r0i myCmd {} arg1 arg2
Стефан Шазелас
источник
Я действительно хотел использовать опцию -f для tail, которая непрерывно печатает строки по мере их поступления. Я не думал, что это будет иметь значение, но, очевидно, это имеет значение. С опцией -f ваше решение не работает.
Ларс
tail -f myFile.txt | xargs -r0i -d '\n' myCmd "{}" "||" "||", Кажется, работает! Спасибо.
Ларс
@Lars, извините, -iопция принимает необязательный аргумент, поэтому -i0не будет работать. Все они должны работать, tail -fкроме последнего, но имейте в виду, что из-за буферизации будет задержка, прежде чем он xargsполучит свои данные tr. Вы можете изменить это, запустив stdbuf -o0 tr '\n' '\0'вместо tr '\n' '\0'.
Стефан Шазелас