代码之家  ›  专栏  ›  技术社区  ›  SebMa

当线路(从管道中输入)包含GNU sed模式时,替换为\r

  •  0
  • SebMa  · 技术社区  · 7 年前

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

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

    你能帮帮我吗?

    2 回复  |  直到 7 年前
        1
  •  1
  •   John1024 David C. Rankin    7 年前

    问题是 -z 使整个文件一次读入。因此 ^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 在任何以 影音: .

    • ta 告诉塞德回到标签上 A. 如果之前的替换命令导致任何更改。这是必要的,因为模式可能重叠,并且 g s 命令不重叠。

        2
  •  1
  •   oguz ismail FCulig    7 年前

    如果awk也是一个选项:

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

    ORS o 输出 R ecord s ePactor;设置为 \n 默认情况下。但在上面的脚本中,其值被动态更改为 \r \n 取决于输入行是否匹配 /^AV:/ (即以 AV: )或者不是。

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

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

    这个 1 在脚本的结尾代表 {print} .

        3
  •  0
  •   SebMa    7 年前

    下面给出一个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:/; 代替 \n \r 每行开头都是 AV:
    • 可选: s/Saving state/\nSaving state/; Saving state 在下面一行,以免覆盖最后一行 影音: