How to select lines between two marker patterns which may occur multiple times with awk/sed

前端 未结 9 1168
离开以前
离开以前 2020-11-22 04:41

Using awk or sed how can I select lines which are occurring between two different marker patterns? There may be multiple sections marked with these

相关标签:
9条回答
  • 2020-11-22 05:09

    something like this works for me:

    file.awk:

    BEGIN {
        record=0
    }
    
    /^abc$/ {
        record=1
    }
    
    /^mno$/ {
        record=0;
        print "s="s;
        s=""
    }
    
    !/^abc|mno$/ {
        if (record==1) {
            s = s"\n"$0
        }   
    }
    

    using: awk -f file.awk data...

    edit: O_o fedorqui solution is way better/prettier than mine.

    0 讨论(0)
  • 2020-11-22 05:15

    I tried to use awk to print lines between two patterns while pattern2 also match pattern1. And the pattern1 line should also be printed.

    e.g. source

    package AAA
    aaa
    bbb
    ccc
    package BBB
    ffffd
    eee
    package CCC
    fff
    ggg
    hhh
    iii
    package DDD
    jjj
    

    should has an ouput of

    package BBB
    ffffd
    eee
    

    Where pattern1 is package BBB, pattern2 is package \w*. Note that CCC isn't a known value so can't be literally matched.

    In this case, neither @scai 's awk '/abc/{a=1}/mno/{print;a=0}a' file nor @fedorqui 's awk '/abc/{a=1} a; /mno/{a=0}' file works for me.

    Finally, I managed to solve it by awk '/package BBB/{flag=1;print;next}/package \w*/{flag=0}flag' file, haha

    A little more effort result in awk '/package BBB/{flag=1;print;next}flag;/package \w*/{flag=0}' file, to print pattern2 line also, that is,

    package BBB
    ffffd
    eee
    package CCC
    
    0 讨论(0)
  • 2020-11-22 05:19

    From the previous response's links, the one that did it for me, running ksh on Solaris, was this:

    sed '1,/firstmatch/d;/secondmatch/,$d'
    
    • 1,/firstmatch/d: from line 1 until the first time you find firstmatch, delete.
    • /secondmatch/,$d: from the first occurrance of secondmatch until the end of file, delete.
    • Semicolon separates the two commands, which are executed in sequence.
    0 讨论(0)
  • 2020-11-22 05:21
    perl -lne 'print if((/abc/../mno/) && !(/abc/||/mno/))' your_file
    
    0 讨论(0)
  • 2020-11-22 05:24

    Use awk with a flag to trigger the print when necessary:

    $ awk '/abc/{flag=1;next}/mno/{flag=0}flag' file
    def1
    ghi1
    jkl1
    def2
    ghi2
    jkl2
    

    How does this work?

    • /abc/ matches lines having this text, as well as /mno/ does.
    • /abc/{flag=1;next} sets the flag when the text abc is found. Then, it skips the line.
    • /mno/{flag=0} unsets the flag when the text mno is found.
    • The final flag is a pattern with the default action, which is to print $0: if flag is equal 1 the line is printed.

    For a more detailed description and examples, together with cases when the patterns are either shown or not, see How to select lines between two patterns?.

    0 讨论(0)
  • 2020-11-22 05:31
    sed '/^abc$/,/^mno$/!d;//d' file
    

    golfs two characters better than ppotong's {//!b};d

    The empty forward slashes // mean: "reuse the last regular expression used". and the command does the same as the more understandable:

    sed '/^abc$/,/^mno$/!d;/^abc$/d;/^mno$/d' file
    

    This seems to be POSIX:

    If an RE is empty (that is, no pattern is specified) sed shall behave as if the last RE used in the last command applied (either as an address or as part of a substitute command) was specified.

    0 讨论(0)
提交回复
热议问题