I didn't find the exact similar question, so i need to ask:
I have a file gist :
...
must_be_intact
bad_line
bad_line
bad_line
match_line
...
I use awk to remove everything before the match but after a space:
'NR==FNR{if (/match_line/) {
i=0;
while(1) {
if (NR-i==/^\s*$/) break;
del[NR-i];
i=i-1;
next
}
}
} !(FNR in del)'
But this does not work correctly. Help improve this code, or you can advise another way.
CodePudding user response:
You have overcomplicated it.
You can just use tac awk tac
operations:
tac file | awk '/^match_line$/,!NF{next} 1' | tac
must_be_intact
must_be_intact
must_be_intact
must_be_intact
must_be_intact
must_be_intact
must_be_intact
must_be_intact
must_be_intact
must_be_intact
must_be_intact
must_be_intact
must_be_intact
must_be_intact
This awk
uses a range from NF==0
(indicating empty line) to a line that just has match_line
and uses next
in action block to skip that part.
CodePudding user response:
$ sed '/^$/,/match_line/{/match_line/!d}' txt
...
must_be_intact
match_line
...
Or
awk -v m="match_line" '{ if($0 ~ /^$/) { while($0 != m) getline } print }' txt
Which yields the same output. I can edit/elaborate later if you want, now I have to go! :)
CodePudding user response:
With your shown samples only, please try following awk
code, written and tested in GNU awk
. Simple explanation would be, setting RS
(record separator) as 1 or more occurrences of new lines till match_line and in main program; substituting first new line with NULL and then printing the lines as per RS.
awk -v RS='\n .*match_line' '{sub(/\n/,"")}1' Input_file