user3798244
user3798244

Reputation: 33

grep regex start with, end with and contain a word

I need extract blocks (between two words: Start and End) of text containing an other word (id).

For example:

2014-07-01 13:26:07,760 Start
2014-07-01 13:26:07,762 id: 456456454
2014-07-01 13:26:07,763 other
2014-07-01 13:26:07,764 End
2014-07-01 13:26:07,764 aaaaaaaa
2014-07-01 13:26:07,764 bbbbbbbb
2014-07-01 13:26:07,765 Start
2014-07-01 13:26:07,765 id: 930939023
2014-07-01 13:26:07,765 something
2014-07-01 13:26:07,766 End
2014-07-01 13:26:07,766 Start
2014-07-01 13:26:07,766 id: 876542
2014-07-01 13:26:07,766 other
2014-07-01 13:26:07,767 End
2014-07-01 13:26:07,767 aaaaaaaa
2014-07-01 13:26:07,767 bbbbbbbb
2014-07-01 13:26:07,767 Start
2014-07-01 13:26:07,767 id: 930939023
2014-07-01 13:26:07,768 something
2014-07-01 13:26:07,768 End
2014-07-01 13:26:07,768 Start
2014-07-01 13:26:07,768 id: 54654
2014-07-01 13:26:07,768 something
2014-07-01 13:26:07,769 End

For id = 930939023, the output is

2014-07-01 13:26:07,765 Start
2014-07-01 13:26:07,765 id: 930939023
2014-07-01 13:26:07,765 something
2014-07-01 13:26:07,766 End
2014-07-01 13:26:07,767 Start
2014-07-01 13:26:07,767 id: 930939023
2014-07-01 13:26:07,768 something
2014-07-01 13:26:07,768 End

Upvotes: 3

Views: 402

Answers (3)

hek2mgl
hek2mgl

Reputation: 158280

You can use awk. Because the script will get more complicated I suggest to store it in a file:

extract.awk:

# Set flag if id was found
/id: 930939023/{f=1}

# On "Start" clear the buffer, reset buffer index i and reset flag
/Start/{b=$0;f=0;next}

# On "End", if the flag was set print the buffer
/End/{
    if(f){
        print b
        print
    }
}

# Append all other lines to buffer
# (Lines between start end will get cleared on next "Start")
{b=b"\n"$0}

... and execute it like this:

awk -f extract.awk file

Output:

2014-07-01 13:26:07,765 Start
2014-07-01 13:26:07,765 id: 930939023
2014-07-01 13:26:07,765 something
2014-07-01 13:26:07,766 End
2014-07-01 13:26:07,767 Start
2014-07-01 13:26:07,767 id: 930939023
2014-07-01 13:26:07,768 something
2014-07-01 13:26:07,768 End

Upvotes: 1

Avinash Raj
Avinash Raj

Reputation: 174874

You could try the below awk command,

$ awk '/Start/ {f=1} /End/ {print;f=0;}f' file | awk -v RS="End" -v ORS="End" '/930939023/'
2014-07-01 13:26:07,765 Start
2014-07-01 13:26:07,765 id: 930939023
2014-07-01 13:26:07,765 something
2014-07-01 13:26:07,766 End
2014-07-01 13:26:07,767 Start
2014-07-01 13:26:07,767 id: 930939023
2014-07-01 13:26:07,768 something
2014-07-01 13:26:07,768 End

Upvotes: 1

jaypal singh
jaypal singh

Reputation: 77185

Here is an option using sed:

sed -n '/Start/{:a;/End/!{N;ba};/930939023/!d;p}' file

Explanation:

sed -n '                  # Suppress default printing
    /Start/ {             # When line contains Start
        :a;               # Create a label a for loop
        /End/! {          # Until a line with End is seen
            N;            # Append the next line to pattern space
            ba            # Go back to label a and repeat
        }
        /930939023/!d;    # If the appended line contains does not contain id, delete it
        p                 # Else print it
 }' file

Upvotes: 7

Related Questions