当行(来自管道)包含具有GNU sed的模式时,用\ r替换\ n

问题描述 投票:1回答:3

我希望使用GNU sed来替换\ n当\ n每行(从管道传入)以指定模式开头但我的sed命令似乎不起作用:

$ cat mpv_all.log | sed -z '/^AV:/s/\n/\r/g'

你能帮我么 ?

sed replace pipe newline carriage-return
3个回答
1
投票

问题是-z导致整个文件立即被读入。因此,如果文件以^AV:开头,则AV:仅匹配。你可能想在每一行上匹配AV:。在这种情况下,请尝试:

sed -Ez ':a; s/((^|[\n\r])AV:[^\n\r]*)\n/\1\r/g ;ta' mpv_all.log

这个怎么运作:

  • -E启用扩展正则表达式。
  • :a定义标签a
  • s/((^|[\n\r])AV:[^\n\r]*)\n/\1\r/g\n取代\r,以AV:开头。
  • ta告诉sed如果先前的替换命令导致任何更改,则返回标签a。这是必要的,因为模式可能重叠,而g命令的s修饰符不会重叠。

1
投票

如果awk也是一个选项:

awk '{ORS=/^AV:/?"\r":"\n"}1' file

ORS是输出记录分隔符;默认设置为\n。但是在上面的脚本中,它的值会动态变为\r\n,具体取决于输入行是否匹配/^AV:/(即以AV:开头)。

ORS=/^AV:/?"\r":"\n"是一个简写

if (/^AV:/)
  ORS="\r"
else
  ORS="\n"

脚本末尾的1代表{print}


0
投票

只是为了给出一个perl实现:

$ perl -p -e '$| = 1;s/\n/\r/g if $_ =~ /^AV:/;s/Saving state/\nSaving state/;' mpv_all.log
  • -p在文件的每一行循环
  • -e在引号中运行perl命令
  • $| = 1; Perl在每一行刷新缓冲区
  • qazxsw poi在s/\n/\r/g if $_ =~ /^AV:/;开头的每一行都用qazxsw poi取代qazxsw poi
  • 可选:\n\r线放在下面一行,以免覆盖AV:的最后一行
© www.soinside.com 2019 - 2024. All rights reserved.