AWK - skip line if line contains pattern and print next line
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I would like to find matching strings (e.g. "this_pattern") and print it along the next following FIVE lines. Mandatory is that the following lines must not contain "this pattern"; rather, this line has to be ignored, and the next following line has to be print instead.
I would have the pattern increment a counter. Then I would have a second statement print a line, and increment the counter, if the counter is already greater than zero. Then if the counter is greater than 5, reset it to zero.
Thanks for your reply.
It's not entirely clear to me what you exactly mean, though.
Maybe a command line would be more helpful to get your point.
Udiubu
The first line above produces the output shown as as an example in #1 above.
It is much smoother that what I proposed. However, being in the newbie subforum, it can be pointed out the shortcuts that awk takes: If an action statement is left off after the pattern, a print is assumed, and if the print has no parameters then $0 is assumed.
So the following is the same as the first line above, but shows the 'hidden' print statement:
About anchoring the pattern, you can make the pattern apply only to the second column using a tilde. You can make the pattern start matching only from the start of the column using a caret.
In this sense, when the first "this_pattern" matches, the next five lines need to be printed, but the second "this_pattern" has to be skipped.
Following, when the second "this_pattern" matches, the next five lines need to be printed. Or is it the case that once a line is skipped, it cannot be retrieved again? An ideal solution would be to say that the next following lines must not contain alphabetic strings: if this is so, ignore it.
Hope this help!
I thank you so much for your valuable help.
Do you need some missing numbers filled in by the script so as to always have exactly five lines after the pattern? If so, how should the numbers be calculated?
@Turbocapitalist - I think the '5' you mention actually comes from the line after this_pattern in the input file, hence the solution is a little more complicated. Not only do you need to provide data from additional lines but you also then need a rewind type option.
If I am understanding correclty, and OP may correct if not, I think the following example is a little clearer:
So assuming the above is the input, I suggest the output is as follows:
Code:
0 this_pattern
1
2
3 # this after second match
4 # this after second match
5 # this after third match
0 this_pattern # this IS second match at line 4 of input
3
4
5 # up to next 0 are after third match
6
7
0 this_pattern # this IS third match at line 7
5
6
7
8
9
As you can see, you are not only printing additional lines that do not include the pattern, but you are also then having to save / rewind back to any pattern lines found along the way
So my suggestion would be to create an array to store the required lines and when you hit the limit, in this case 5, you print out the array that has this many items
yes, would be nice to see a better input/output example
What I can imagine is to store the state somehow and print lines according to that state:
Code:
awk '
# but obviously this line does not meet the requirements
# so need to be improved
/pattern/ { state=found; nr=NR }
state==found { skip this line, but remember to print next 5 }
"within next 5 and /pattern/" { skip this line, recalculate "next 5" }
"within next 5 and no pattern" { print }
'
but still not sure if this was the real goal (or something else)
@grail: you got exactly the point and your example is perfect to test.
There should exactly be a rewind back to any pattern lines found along the way.
However I honestly do not really know how to implement it.
@MadeInGermany: this command works, but indeed once you skip a matched string along the next lines, it is simply lost and not recoverable.
awk '/this_pattern/ {if (cnt) next; cnt=6} (cnt && cnt--)'
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.