简体   繁体   中英

how to print lines matching between two patterns but second pattern existing multiple times in a file using sed command or awk command?

I have this input file F1 :

Good morning!
Have a nice day;
see you again the next day;
Bye;

I want to print the lines between "Have" and "day". I tried with this command: *sed -n '/Have/,/day/ p*' F1 output is: Have a nice day But I want second line also to be printed as it also has the same pattern "day". Desired output: Have a nice day; see you again the next day;

Can anyone help me with this? Thanks in advance.

This might work for you (GNU sed):

sed  '/Have/{:a;x;s/^\(.*\n.*day[^\n]*\).*/\1/p;x;h;d};H;$!d;ba' file

The command /Have/,/day/ collects the shortest number of lines between Have and day , is what you require the longest? If so here is such a solution.

Store lines in the hold space which contain Have in the first line, then at each occurrence of the the word Have delete lines following the last day of the previous collection and print them. At end-of-file repeat this one further time.

NB The command /Have/,/day/ will collect all lines from the first containing Have to the end-of-file if no line containing day is encountered. The above solution prints only when both conditions are met.

This should work in awk . Basically, it makes 2 passes - which is why F1 appears twice at the end of the command as a file to process.

On the first pass (FNR==NR), it saves the line number in s (start) of the first occurrence of "Have", and it saves the line number of the last occurrence in e (end) of the word "day".

On the second pass, (FNR!=NR), it prints lines between s and e (start and end).

awk '/Have/&&s==0{s=FNR} /day/&&FNR==NR{e=NR} (FNR!=NR)&&(FNR>=s)&&(FNR<=e)' F1 F1

The following would do it one-way

awk '/Have/           { p=1 }
     /day/  && (p==1) { p=2; print; next }
     !/day/ && (p==2) { p = 0 }
     p' <file>

What we do here is to keep track of a label p . If Have is found, set p=1 , if day is found, set p=2 , also print and move to the next line. If p>1 it means we found a day , if that line does not contain day set the print-label back to zero, otherwise print.

The output is

Have a nice day;
see you again the next day;

This will print blocks and not until the last day .

An input of the form

Good morning!
Have a nice day;
see you again the next day;
Bye;

Good morning!
Have a nice day;
see you again the next day;
Bye;

will output:

Have a nice day;
see you again the next day;
Have a nice day;
see you again the next day;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM