当行(来自管道)包含 GNU sed 模式时,用 \r 替换 \n
Replace \n by \r when line (comming from a pipe) contains pattern with GNU sed
当每一行(来自管道)以指定的模式开始时,我想使用 GNU sed 将 \n 替换为 \r,但我的 sed 命令似乎不起作用:
$ cat mpv_all.log | sed -z '/^AV:/s/\n/\r/g'
你能帮帮我吗?
问题是 -z
导致整个文件被一次读入。因此,^AV:
仅在文件以 AV:
开头时匹配。您可能希望在每一行上匹配 AV:
。在这种情况下,尝试:
sed -Ez ':a; s/((^|[\n\r])AV:[^\n\r]*)\n/\r/g ;ta' mpv_all.log
工作原理:
-E
打开扩展正则表达式。
:a
定义标签 a
.
在以 AV:
.[=43 开头的任何行的末尾,s/((^|[\n\r])AV:[^\n\r]*)\n/\r/g
将 \n
替换为 \r
=]
ta
告诉 sed 返回到标签 a
如果先前的替换命令导致任何更改。这是必要的,因为模式可以重叠,并且 s
命令的 g
修饰符不会重叠。
如果 awk 也是一个选项:
awk '{ORS=/^AV:/?"\r":"\n"}1' file
ORS
是 output record separator;默认设置为 \n
。但在上面的脚本中,它的值动态更改为 \r
或 \n
,具体取决于输入行是否匹配 /^AV:/
(即以 AV:
开头)。
ORS=/^AV:/?"\r":"\n"
是 shorthand 对于
if (/^AV:/)
ORS="\r"
else
ORS="\n"
脚本末尾的1
代表{print}
。
只是给出一个 perl 实现:
$ perl -p -e '$| = 1;s/\n/\r/g if $_ =~ /^AV:/;s/Saving state/\nSaving state/;' mpv_all.log
-p
在文件的每一行循环
-e
运行引号中的 perl 命令
$| = 1;
Perl 在每一行刷新缓冲区
s/\n/\r/g if $_ =~ /^AV:/;
在以 AV:
开头的每一行中将 \n
替换为 \r
- 可选:
s/Saving state/\nSaving state/;
将 Saving state
行放在下一行,以免覆盖包含 AV:
的最后一行
当每一行(来自管道)以指定的模式开始时,我想使用 GNU sed 将 \n 替换为 \r,但我的 sed 命令似乎不起作用:
$ cat mpv_all.log | sed -z '/^AV:/s/\n/\r/g'
你能帮帮我吗?
问题是 -z
导致整个文件被一次读入。因此,^AV:
仅在文件以 AV:
开头时匹配。您可能希望在每一行上匹配 AV:
。在这种情况下,尝试:
sed -Ez ':a; s/((^|[\n\r])AV:[^\n\r]*)\n/\r/g ;ta' mpv_all.log
工作原理:
-E
打开扩展正则表达式。:a
定义标签a
.
在以 s/((^|[\n\r])AV:[^\n\r]*)\n/\r/g
将\n
替换为\r
=]ta
告诉 sed 返回到标签a
如果先前的替换命令导致任何更改。这是必要的,因为模式可以重叠,并且s
命令的g
修饰符不会重叠。
AV:
.[=43 开头的任何行的末尾,如果 awk 也是一个选项:
awk '{ORS=/^AV:/?"\r":"\n"}1' file
ORS
是 output record separator;默认设置为 \n
。但在上面的脚本中,它的值动态更改为 \r
或 \n
,具体取决于输入行是否匹配 /^AV:/
(即以 AV:
开头)。
ORS=/^AV:/?"\r":"\n"
是 shorthand 对于
if (/^AV:/)
ORS="\r"
else
ORS="\n"
脚本末尾的1
代表{print}
。
只是给出一个 perl 实现:
$ perl -p -e '$| = 1;s/\n/\r/g if $_ =~ /^AV:/;s/Saving state/\nSaving state/;' mpv_all.log
-p
在文件的每一行循环-e
运行引号中的 perl 命令$| = 1;
Perl 在每一行刷新缓冲区s/\n/\r/g if $_ =~ /^AV:/;
在以AV:
开头的每一行中将 - 可选:
s/Saving state/\nSaving state/;
将Saving state
行放在下一行,以免覆盖包含AV:
的最后一行
\n
替换为 \r