SED: addressing two lines before match

后端 未结 6 1653
梦如初夏
梦如初夏 2021-01-20 05:20

Print line, which is situated 2 lines before the match(pattern).

I tried next:

sed -n \': loop
/.*/h
:x
{n;n;/cen/p;}
s/./c/p
t x
s/n/c/p
t loop
{g;p         


        
相关标签:
6条回答
  • 2021-01-20 05:56

    I've tested your sed command but the result is strange (and obviously wrong), and you didn't give any explanation. You will have to save three lines in a buffer (named hold space), do a pattern search with the newest line and print the oldest one if it matches:

    sed -n '
        ## At the beginning read three lines.
        1 { N; N }
        ## Append them to "hold space". In following iterations it will append
        ## only one line.
        H 
        ## Get content of "hold space" to "pattern space" and check if the 
        ## pattern matches. If so, extract content of first line (until a 
        ## newline) and exit.
        g
        /^.*\nsix$/ { 
            s/^\n//
            P
            q 
        }
        ## Remove the old of the three lines saved and append the new one.
        s/^\n[^\n]*//
        h
    ' infile
    

    Assuming and input file (infile) with following content:

    one
    two
    three
    four
    five
    six
    seven
    eight
    nine
    ten
    

    It will search six and as output will yield:

    four
    
    0 讨论(0)
  • 2021-01-20 06:00

    The script:

      sed -n "1N;2N;/XXX[^\n]*$/P;N;D"
    

    works as follows:

    • Read the first three lines into the pattern space, 1N;2N
    • Search for the test string XXX anywhere in the last line, and if found print the first line of the pattern space, P
    • Append the next line input to pattern space, N
    • Delete first line from pattern space and restart cycle without any new read, D, noting that 1N;2N is no longer applicable
    0 讨论(0)
  • 2021-01-20 06:01

    If you can use awk try this:

    awk  '/pattern/ {print b} {b=a;a=$0}' file
    

    This will print two line before pattern

    0 讨论(0)
  • 2021-01-20 06:04

    Here are some other variants:

    awk '{a[NR]=$0} /pattern/ {f=NR} END {print a[f-2]}' file
    

    This stores all lines in an array a. When pattern is found store line number.
    At then end print that line number from the file.
    PS may be slow with large files


    Here is another one:

    awk 'FNR==NR && /pattern/ {f=NR;next} f-2==FNR' file{,}
    

    This reads the file twice (file{,} is the same as file file)
    At first round it finds the pattern and store line number in variable f
    Then at second round it prints the line two before the value in f

    0 讨论(0)
  • 2021-01-20 06:05

    This might work for you (GNU sed):

    sed -n ':a;$!{N;s/\n/&/2;Ta};/^PATTERN\'\''/MP;$!D' file
    

    This will print the line 2 lines before the PATTERN throughout the file.

    0 讨论(0)
  • 2021-01-20 06:08

    This one with grep, a bit simpler solution and easy to read [However need to use one pipe]: grep -B2 'pattern' file_name | sed -n '1,2p'

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