当行(从管道提交)包含GNU sed的模式时,替换为\r\n

当行(从管道提交)包含GNU sed的模式时,替换为\r\n,sed,replace,pipe,newline,carriage-return,Sed,Replace,Pipe,Newline,Carriage Return,当每一行(从管道中输入)以指定的模式开始,但我的sed命令似乎不起作用时,我想与GNU sed一起使用,以\n替换为\r: $ 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/\1\r/g ;ta' mpv_all.log 工作原

当每一行(从管道中输入)以指定的模式开始,但我的sed命令似乎不起作用时,我想与GNU sed一起使用,以\n替换为\r:

$ 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/\1\r/g ;ta' mpv_all.log
工作原理:

  • -E
    打开扩展正则表达式

  • :a
    定义标签
    a

  • s/((^ |[\n\r])AV:[^\n\r]*)\n/\1\r/g
    替换为以
    AV:
    开头的任何行末尾的
    \n

  • ta
    告诉sed,如果先前的替换命令导致任何更改,则返回标签
    a
    。这是必要的,因为模式可能重叠,
    s
    命令的
    g
    修饰符不重叠


如果awk也是一个选项:

awk '{ORS=/^AV:/?"\r":"\n"}1' file
ORS
isoutputrecordseparator;默认设置为
\n
。但在上面的脚本中,根据输入行是否匹配
/^AV:///code>(即以
AV:
开头),其值将动态更改为
\r
\n

ORS=/^AV:/?“\r”:“\n”

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命令
  • $|=1Perl在每一行刷新缓冲区
  • s/\n/\r/g如果$\=~/^AV:/
    \n
    替换为
    \r
    AV:
  • 可选:
    s/保存状态/\n保存状态/
    保存状态
    行放在下面一行,以免覆盖包含
    AV:

这个regexp对我来说似乎有点复杂。是否可以在不使用
sed
-z
选项的情况下替换
\n
?在正常情况下,sed在创建图案空间之前删除
\n
,然后在图案空间的末尾添加一个
\n
,然后再进行打印。所以,你确实需要一些特殊的处理。如果你使用了GNU,那么
-z
是一个好方法。我也喜欢这个方法,但我不理解它。你能在你的回答中解释一下awk指令末尾的
标记和
1
的含义吗?总结一下(对于以后像我这样的其他人):awk指令末尾的
1
意味着打印每一行。因此,它可以被单个
打印所取代右括号前。