使用awk更新文件以删除多行字符串中出现的模式

时间:2017-03-31 23:16:02

标签: awk sed

我想处理和修改几个YAML文件,使用awk更新和删除下面的输入文件。

以下是输入文件示例:

    #Modify this
    sss:
      - ccc:
          brr: 'mmm'
          jdk: 'jdk8'
      - bbb:
          brr: 'rel/bbb'
          jdk: 'jdk8'
      - aaa:
          brr: 'rel/aaa'
          jdk: 'jdk7'


    #dont change me
    sss: ccc
    ppp: 'vvv'
    pname: 'vvv'
    brr: 'mmm'
    jdk: jdk8
    jdks:
      - jdk8
      - jdk7
    file:
      - test:
          exec: 'input'

下面的awk片段处理后的预期输出:

    #Modify this
    sss:
      - ddd:
          brr: 'mmm'
          jdk: 'jdk8'
      - ccc:
          brr: 'rel/ccc'
          jdk: 'jdk8'
      - bbb:
          brr: 'rel/bbb'
          jdk: 'jdk8'

    #dont change me
    sss: ccc
    ppp: 'vvv'
    pname: 'vvv'
    jdk: jdk8
    jdks:
      - jdk8
      - jdk7
    file:
      - test:
          exec: 'input'

直到现在我已经有了一个awk片段,它处理输入的第一部分而没有任何问题:

/sss:/ { sss = 1; }
/- ccc:/ { ccc = 1; i = substr($0, 1, index($0, "-")-1); next; }
$1 == "brr:" && $2 == "'mmm'" {
    if (sss && ccc) {
        print i "- ddd:";
        print i "    brr: 'mmm'";
        print i "    jdk: 'jdk8'";
        print i "- ccc:";
        print i "    brr: 'rel/ccc'";
        sss = 0; ccc = 0;
    }
    next;
}
{ print }

如何改进上述代码段以删除这些行:

    - aaa:
        brr: 'rel/aaa'
        jdk: 'jdk7'
        file: optional-line

并确保不会更新输入的第二部分,其中brr: 'mmm'该行被删除。

1 个答案:

答案 0 :(得分:0)

$ cat tst.awk
/^[[:space:]]*sss:[[:space:]]*$/ { print; inBlocks=1 }
inBlocks {
    if ( /^[[:space:]]*-/ ) {
        ++numBlocks
    }

    block[numBlocks,++blockNumLines[numBlocks]] = $0

    if ( !NF ) {
        blockNr = 1
        numLines = blockNumLines[blockNr]
        line = block[blockNr,1]
        sub(/[[:alpha:]]+/,"ddd",line)
        print line
        for (lineNr=2; lineNr<=numLines; lineNr++) {
            print block[blockNr,lineNr]
        }

        type = block[blockNr,1]
        gsub(/[^[:alpha:]]+/,"",type)
        sub(/[^[:space:]]+[[:space:]]*$/,"\047rel/"type"\047",block[blockNr,2])

        for (blockNr=1; blockNr<numBlocks; blockNr++) {
            numLines = blockNumLines[blockNr]
            for (lineNr=1; lineNr<=numLines; lineNr++) {
                print block[blockNr,lineNr]
            }
        }
        inBlocks = 0
        numBlocks = 0
    }
}
!inBlocks

$ awk -f tst.awk file
    #Modify this
    sss:
      - ddd:
          brr: 'mmm'
          jdk: 'jdk8'
      - ccc:
          brr: 'rel/ccc'
          jdk: 'jdk8'
      - bbb:
          brr: 'rel/bbb'
          jdk: 'jdk8'


    #dont change me
    sss: ccc
    ppp: 'vvv'
    pname: 'vvv'
    brr: 'mmm'
    jdk: jdk8
    jdks:
      - jdk8
      - jdk7
    file:
      - test:
          exec: 'input'