LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This 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


Reply
  Search this Thread
Old 05-22-2012, 04:20 PM   #1
ezekieldas
Member
 
Registered: Mar 2010
Posts: 122

Rep: Reputation: 16
grep this and this2 and that and that2


I'm probably overlooking something obvious here. I've found a number of pages which discuss
grep and logical AND but none seem to accomplish what I need.

I have a script (which I cannot modify). It outputs (something like) the following:

Code:
ViewAsString=[1.2.3.1:11|3] [1.2.3.1:11, 1.2.3.2:122, 1.2.3.8:123, 1.2.3.4:124]
I want to grab an exit code of 0 if my list of ipaddrs prints, 1 if it doesn't. I need a one liner (not another script) so grep seems to be a good choice here. The following ipaddrs _must_ always be present, even though one of them repeats: 1.2.3.1, 1.2.3.2, 1.2.3.8, 1.2.3.4

So I can do this
Code:
'foo.sh | grep 1.2.3.1 | grep 1.2.3.2 | grep 1.2.3.4 | grep 1.2.3.8'
But that seems too elaborate. There's a previous discussion here that was close but it didn't actually work:
Code:
foo.sh | awk '/1.2.3.1/ && /6.6.6.6/'
echo $?
0
How can I use grep or awk (or some other common tool) to get all 4 ipaddrs (no more, no less)?
 
Old 05-22-2012, 05:15 PM   #2
bigrigdriver
LQ Addict
 
Registered: Jul 2002
Location: East Centra Illinois, USA
Distribution: Debian stable
Posts: 5,886

Rep: Reputation: 351Reputation: 351Reputation: 351Reputation: 351
I can't help you with grabbing exit codes, but the grep for number patterns works with the -e option.

Your code:
Code:
'foo.sh | grep 1.2.3.1 | grep 1.2.3.2 | grep 1.2.3.4 | grep 1.2.3.8'
My edit:
Code:
'foo.sh | grep -e 1.2.3.1 -e 1.2.3.2 -e 1.2.3.4 -e 1.2.3.8'
I made a simple list of number patterns running from 1.2.3.1 to 1.2.3.9, then ran grep with the -e options as shown above, and it returned only the desired numbers from the list.
 
Old 05-22-2012, 05:25 PM   #3
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978
You have to force awk to return an exit code if the expression is not true:
Code:
foo.sh | awk '!(/1.2.3.1/ && /1.2.3.2/ && /1.2.3.4/ && /1.2.3.8/){exit 1}'
In addition, maybe you have to refine the regular expressions, since /1.2.3.1/ matches 1.2.3.10, 1.2.3.11 and so on. Maybe adding a colon at the end of the addresses, as in your example?
 
Old 05-22-2012, 05:48 PM   #4
Tinkster
Moderator
 
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 23,067
Blog Entries: 11

Rep: Reputation: 910Reputation: 910Reputation: 910Reputation: 910Reputation: 910Reputation: 910Reputation: 910Reputation: 910
Quote:
Originally Posted by colucix View Post
You have to force awk to return an exit code if the expression is not true:
Code:
foo.sh | awk '!(/1.2.3.1/ && /1.2.3.2/ && /1.2.3.4/ && /1.2.3.8/){exit 1}'
In addition, maybe you have to refine the regular expressions, since /1.2.3.1/ matches 1.2.3.10, 1.2.3.11 and so on. Maybe adding a colon at the end of the addresses, as in your example?
And let's not forget the special meaning of the dot ... ;}

His string would also match e.g.: 1.213.1 ... back-slashes are our friends!



Cheers,
Tink
 
Old 05-22-2012, 05:57 PM   #5
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.9, Centos 7.3
Posts: 17,347

Rep: Reputation: 2365Reputation: 2365Reputation: 2365Reputation: 2365Reputation: 2365Reputation: 2365Reputation: 2365Reputation: 2365Reputation: 2365Reputation: 2365Reputation: 2365
I tried these test
Code:
$ echo '1 x'|grep -e 1 -e 2
1 x

$ echo $?
0

$ echo '1 x'|grep -e g -e z
$ echo $?
1

$ echo 1|grep -e 1 -e x
1
$ echo $?
0
which to me implies -e does a logical OR, not a logical AND
 
Old 05-22-2012, 07:08 PM   #6
whizje
Member
 
Registered: Sep 2008
Location: The Netherlands
Distribution: Slackware64 current
Posts: 592

Rep: Reputation: 140Reputation: 140
Code:
grep -o  "[1][.][2][.][3][.][1248]"|uniq | wc -w
Search for ip string pipe through uniq and count if count is 4 you got your string.
for uniq the repeated lines need to be adjacent else you can use
Code:
grep -o  "[1][.][2][.][3][.][1248]"|sort -u | wc -w
a possible test
grep -o  "[1][.][2][.][3][.][1248]"|sort -u |[ "$(wc -w)" -eq "4" ];echo $?

Last edited by whizje; 05-23-2012 at 01:57 AM. Reason: error
 
Old 05-23-2012, 09:51 AM   #7
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959Reputation: 1959
Yes, grep's (and sed's) "-e" expressions (including regex combinations) act like OR, not AND.

Think about how it works. Each line is read in in sequence, and compared to all the expressions given. If it matches any of them, it returns it as output. Then the next line is read.

So no, if the file must contain ALL of the given expressions, then a single grep can't handle it. You have to use awk, or another tool like perl or even shell scripting, that can keep track of what has and hasn't been found as it iterates through the file.

It would generally also take something more complex than a short one-liner as well. Indeed Colucix's offering:

Code:
awk '!(/1.2.3.1/ && /1.2.3.2/ && /1.2.3.4/ && /1.2.3.8/){exit 1}'
...won't really do, as it stands, because the test is checking each record (i.e. line) at a time for the existence of all entries, not the entire file as a whole.

It can be made to work, however, if the file is small enough to sit in memory, and you're using a compatible version of awk (i.e. gnu). Just redefine the record separator to null, which should make it treat the whole file as a single record. In which case I'd probably go with something more like this:

Code:
awk -v RS='' '{ if (/1[.]2[.]3[.]1/ && /1[.]2[.]3[.]2/ && /1[.]2[.]3[.]4/ && /1[.]2[.]3[.]8/ ) { print "all entries found"; exit 0 } else { print "something not found" ; exit 1 }}' infile.txt
The print commands are optional, of course I just put them there to clearly illustrate the output.

But if the file is too large for the above, you'd have to a more complex run-through of each line in turn, setting a variable for each matched string, say, then testing those for final compliance at the end.

Here's a proof of concept I just whipped up that appears to work, although it could undoubtedly be made much cleaner with a bit of effort.

Code:
awk '/1[.]2[.]3[.]1/ { a=1 } ; /1[.]2[.]3[.]2/ { b=1 } ; /1[.]2[.]3[.]4/ { c=1 } ; /1[.]2[.]3[.]8/ { d=1 } END{ x=a+b+c+d ; if ( x == 4 ){ print "all 4 found" ; exit 0 } else print "something not found" ; exit 1 }' infile.txt

Last edited by David the H.; 05-23-2012 at 09:55 AM. Reason: simplified the code a bit
 
Old 05-23-2012, 01:00 PM   #8
whizje
Member
 
Registered: Sep 2008
Location: The Netherlands
Distribution: Slackware64 current
Posts: 592

Rep: Reputation: 140Reputation: 140
Quote:
Originally Posted by David the H. View Post
So no, if the file must contain ALL of the given expressions, then a single grep can't handle it. You have to use awk, or another tool like perl or even shell scripting, that can keep track of what has and hasn't been found as it iterates through the file.
You can get all the expressions with a single grep, but you need to verify if the result contains the four different ip's.
Code:
grep -o  "[1][.][2][.][3][.][1248]"|sort -u |[ "$(wc -w)" -eq "4" ];echo $?
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
grep has no effect - does not grep anything in this for loopa LinuxChiq Linux - Newbie 2 12-01-2011 09:03 PM
[SOLVED] Grep -p for Linux, Trying to grep a paragraph. ohijames Linux - Newbie 5 07-22-2010 02:09 PM
Trying to understand pipes - Can't pipe output from tail -f to grep then grep again lostjohnny Linux - Newbie 15 03-12-2009 10:31 PM
how to grep multiple filters with grep LinuxLover Linux - Enterprise 1 10-18-2007 07:12 AM
ps -ef|grep -v root|grep apache<<result maelstrombob Linux - Newbie 1 09-24-2003 11:38 AM


All times are GMT -5. The time now is 05:03 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration