使用tail时将换行符转换为以空分隔符


20

如何将输出更改tail为使用以空终止的行而不是换行?

我的问题与此相似:如何在bash中以空定界输入执行“ head”和“ tail”操作?,但不同之处在于我想执行以下操作:

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

Answers:


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

如果要使用NUL分隔的最后10条记录myFile.txt(但那不是文本文件),则\n必须\0在调用之前将转换为,tail这意味着必须完全读取该文件:

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

编辑(因为你改变了tailtail -f你的问题):

上面的最后一个显然对没有意义tail -f

xargs -d '\n'一会工夫,但对于其他的人,你就会有一个缓冲的问题。在:

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

tr当它没有到达终端(这里是管道)时,缓冲其输出。IE,它将不会写任何东西,直到它已经积累了一个充满了要写入数据的缓冲区(类似于8kiB)。这意味着myCmd将被批量调用。

在GNU或FreeBSD系统上,您可以tr使用以下stdbuf命令更改的缓冲行为:

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

我实际上是想在尾巴上使用-f选项,该选项会在输入行时连续打印。我认为这并不重要,但显然确实如此。使用-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'
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.