[SOLVED] AWK print line only if next line matches a string
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 am relatively new to awk and I was searching all over the place for the answer to this, but can't really find anything valid. I was wondering how to only print a line if the next line matches a string.
I started with something like this:
NODE_1
port 1
description blah
port 2
description blah blah
NODE_2
port 1
description blah
port 2
description blah
NODE_3
port 1
port 2
NODE_4
port 1
port 2
NODE_5
port 1
port 2
NODE_6
port 1
description blahdy blah
port 2
description floop-a-doop
Originally my intention was to exclude any ports that don't have descriptions, while leaving the node names intact.
...to print all "NODE" lines and any "description" line as well as the previous "port" line above it (kudos to crts for that answer).
Now I get this:
NODE_1
port 1
description blah
port 2
description blah blah
NODE_2
port 1
description blah
port 2
description blah
NODE_3
NODE_4
NODE_5
NODE_6
port 1
description blahdy blah
port 2
description floop-a-doop
Which I thought was what was needed, but apparently we don't need the node names of devices that have ports without descriptions at all. So I essentially need to get rid of the node names that are not followed by the string "port". Desired output should look like this:
NODE_1
port 1
description blah
port 2
description blah blah
NODE_2
port 1
description blah
port 2
description blah
NODE_6
port 1
description blahdy blah
port 2
description floop-a-doop
Any help would be greatly appreciated, and if it would help, I can post the actual content rather than all the "blahs" everything if that helps.
Thanks in advance!
Last edited by wolverene13; 10-02-2011 at 03:39 PM.
Reason: code example had incorrect variable names
awk '/^port/{port=$0}/^description/{print port;print $0}' nodes
port 1
description blah
port 2
description blah blah
port 1
description blah
port 2
description blah
port 1
description blahdy blah
port 2
description floop-a-doop
Works as desired w/ the current data sample.
That looks like it would work, but it doesn't appear to print the node names - while I need the ports and their descriptions, I do also need the node name listed before each set of ports and their respective descriptions.
That looks like it would work, but it doesn't appear to print the node names - while I need the ports and their descriptions, I do also need the node name listed before each set of ports and their respective descriptions.
Oops - easy fix.
Code:
awk '/^NODE/{print $0}/^port/{port=$0}/^description/{print port;print $0}' nodes
NODE_1
port 1
description blah
port 2
description blah blah
NODE_2
port 1
description blah
port 2
description blah
NODE_3
NODE_4
NODE_5
NODE_6
port 1
description blahdy blah
port 2
description floop-a-doop
awk '/^NODE/{print $0}/^port/{port=$0}/^description/{print port;print $0}' nodes
NODE_1
port 1
description blah
port 2
description blah blah
NODE_2
port 1
description blah
port 2
description blah
NODE_3
NODE_4
NODE_5
NODE_6
port 1
description blahdy blah
port 2
description floop-a-doop
Well, that's kind of back to square 1; Essentially I need a way to make NODE_3, NODE_4, and NODE_5 go away because they don't have any ports with descriptions on them.
EDIT: Essentially I need something that says: "If the next line after NODE does not begin with "port", don't print NODE either."
Last edited by wolverene13; 10-02-2011 at 04:36 PM.
Reason: clarification
Well, that's kind of back to square 1; Essentially I need a way to make NODE_3, NODE_4, and NODE_5 go away because they don't have any ports with descriptions on them.
EDIT: Essentially I need something that says: "If the next line after NODE does not begin with "port", don't print NODE either."
That description is actually wrong. What you want is: "If the line after port isn't description
don't print node and port either."
Code:
awk '/^NODE/{node=$0}/^port/{port=$0}/^description/{if(prev!=node){print node};print port;print $0;prev=node}' nodesNODE_1
port 1
description blah
port 2
description blah blah
NODE_2
port 1
description blah
port 2
description blah
NODE_6
port 1
description blahdy blah
port 2
description floop-a-doop
That description is actually wrong. What you want is: "If the line after port isn't description
don't print node and port either."
Code:
awk '/^NODE/{node=$0}/^port/{port=$0}/^description/{if(prev!=node){print node};print port;print $0;prev=node}' nodes
NODE_1
port 1
description blah
port 2
description blah blah
NODE_2
port 1
description blah
port 2
description blah
NODE_6
port 1
description blahdy blah
port 2
description floop-a-doop
Cheers,
Tink
Perfect! That's exactly what I needed! Thanks a lot!!
I'd hate to bother you, but if I'm understanding the syntax right:
awk '/^NODE/{node=$0} is essentially "search for lines beginning with "NODE" and "remember" those lines in $0 and collectively call them "node""
/^port/{port=$0} is pretty much the same thing, except searching for lines containing "port", which then join all the "NODE" lines in $0, and collectively called "port"
This is where it gets fuzzy for me:
/^description/{if(prev!=node){print node};print port;print $0;prev=node}'
Does that mean "search for lines beginning with "description", create a variable that is called "prev", then if prev does not equal anything in "node", print everything in "node", print everything in "port", and everything "remembered" in $0" then prev=node? Sorry if that's way off, but I'm fairly new to awk and like to actually learn what I'm doing, rather then just regurgitate the answers that I receive. Thanks for the help!
Perfect! That's exactly what I needed! Thanks a lot!!
I'd hate to bother you, but if I'm understanding the syntax right:
awk '/^NODE/{node=$0} is essentially "search for lines beginning with "NODE" and "remember" those lines in $0 and collectively call them "node""
/^port/{port=$0} is pretty much the same thing, except searching for lines containing "port", which then join all the "NODE" lines in $0, and collectively called "port"
Not quite ... there's no "collective" there. port and node are variables
that will get populated every time a line begins w/ NODE or port, respectively.
The whole string of expressions gets applied to each line of your nodes file.
Quote:
Originally Posted by wolverene13
This is where it gets fuzzy for me:
/^description/{if(prev!=node){print node};print port;print $0;prev=node}'
Does that mean "search for lines beginning with "description", create a variable that is called "prev", then if prev does not equal anything in "node", print everything in "node", print everything in "port", and everything "remembered" in $0" then prev=node? Sorry if that's way off, but I'm fairly new to awk and like to actually learn what I'm doing, rather then just regurgitate the answers that I receive. Thanks for the help!
The prev variable and its comparison against node are there so we don't
print NODE for each port line w/ a description, in other words to avoid
the following output:
Code:
NODE_1
port 1
description blah
NODE_1
port 2
description blah blah
NODE_2
port 1
description blah
NODE_2
port 2
description blah
NODE_6
port 1
description blahdy blah
NODE_6
port 2
description floop-a-doop
Not quite ... there's no "collective" there. port and node are variables
that will get populated every time a line begins w/ NODE or port, respectively.
The whole string of expressions gets applied to each line of your nodes file.
The prev variable and its comparison against node are there so we don't
print NODE for each port line w/ a description, in other words to avoid
the following output:
Code:
NODE_1
port 1
description blah
NODE_1
port 2
description blah blah
NODE_2
port 1
description blah
NODE_2
port 2
description blah
NODE_6
port 1
description blahdy blah
NODE_6
port 2
description floop-a-doop
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.