【问题标题】:Use sed to replace word in 2-line pattern使用 sed 替换 2 行模式中的单词
【发布时间】:2014-11-05 14:52:07
【问题描述】:

我尝试使用 sed 将 2 行模式中的一个单词替换为另一个单词。当在一行中找到模式'MACRO“something”'时,然后在下一行中将'BLOCK'替换为'CORE'。 “某物”将被放入参考并打印出来。

我的输入数据:

MACRO ABCD
  CLASS BLOCK ;
  SYMMETRY X Y ;

期望的结果:

MACRO ABCD
  CLASS CORE ;
  SYMMETRY X Y ;

到目前为止我在 sed 中的尝试:

sed 's/MACRO \([A-Za-z0-9]*\)/,/  CLASS BLOCK ;/MACRO \1\n  CLASS CORE ;/g' input.txt

上面的方法没有给出消息:

sed: -e expression #1, char 30: unknown option to `s'

我错过了什么?

我也对 perl 中的单行解决方案持开放态度。

谢谢, 格特

【问题讨论】:

  • 所以您想在修改文件的同时将“ABCD”发送到stdout

标签: perl sed substitution


【解决方案1】:

在 slurp 模式下使用 perl 单行:

perl -0777 -pe 's/MACRO \w+\n  CLASS \KBLOCK ;/CORE ;/g' input.txt

或使用流式传输示例:

perl -pe '
    s/^\s*\bCLASS \KBLOCK ;/CORE ;/ if $prev;
    $prev = $_ =~ /^MACRO \w+$/
  ' input.txt

说明:

开关

  • -0777: Slurp 整个文件
  • -p:为输入文件中的每一行创建一个 while(<>){...; print} 循环。
  • -e:告诉perl 在命令行上执行代码。

【讨论】:

    【解决方案2】:

    当在一行中找到模式“MACRO “something””时,然后在 下一行将“BLOCK”替换为“CORE”。

    sed 作用于输入的。如果您想对指定模式的下一行执行替换,则需要先将其添加到模式空间中。

    以下可能对您有用:

    sed '/MACRO/{N;s/\(CLASS \)BLOCK/\1CORE/;}' filename
    

    引用文档:

    `N'

     Add a newline to the pattern space, then append the next line of
     input to the pattern space.  If there is no more input then sed
     exits without processing any more commands.
    

    如果您想在尝试中使用地址范围,那么您需要:

     sed '/MACRO/,/CLASS BLOCK/{s/\(CLASS\) BLOCK/\1 CORE/}' filename
    

    我不确定为什么需要反向引用来替换宏名称。

    【讨论】:

    • 这在大多数情况下可能会起作用,但是如果替换模式在包含 MACRO 的行中,则不会修改第二行。也许sed '/MACRO/{n;s/\(CLASS \)BLOCK/\1CORE/;}' file 符合要求?
    【解决方案3】:

    你也可以试试这个 awk 命令,

    awk '{print}/MACRO/ {getline; sub (/BLOCK/,"CORE");{print}}' file
    

    它按原样打印所有行,并在看到一行上的单词 MACRO 时执行替换操作。

    【讨论】:

    • awk '1; /MACRO/ {getline;sub(/BLOCK/,"CORE");print}' 与您发布的相同,但更简洁。
    【解决方案4】:

    由于getline有这么多陷阱,我尽量不使用它,所以:

    awk '/MACRO/ {a++} a==1 {sub(/BLOCK/,"CORE")}1' file
    MACRO ABCD
      CLASS CORE ;
      SYMMETRY X Y ;
    

    【讨论】:

      【解决方案5】:

      这个可以的

      #!awk -f
      BEGIN {
        RS = ";"
      }
      /MACRO/ {
        sub("BLOCK", "CORE")
      }
      {
        printf s++ ? ";" $0 : $0
      }
      
      • “行”以;结尾
      • sub BLOCK for CORE in "lines" with MACRO
      • 打印; 后跟“line”,除非是第一行

      【讨论】:

        猜你喜欢
        • 2019-01-22
        • 1970-01-01
        • 1970-01-01
        • 2013-09-12
        • 1970-01-01
        • 2012-03-07
        • 2012-04-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多