views:

349

answers:

5

I need a way to simplify this command:

grep 'SEARCHTERM' server.log | grep -v 'PHHIABFFH' | grep -v 'Stats'

It should find all the lines including SEARCHTERM but exclude if one of the SEARCHTERM lines includes PHHIABFFH or Stats.

+6  A: 

Why do you want to 'simplify' this pipe? Un*x commandline tools are made to be chained in a way like this.

Edit

Some of answers suggest using features of specific versions of grep. I like this but it is very possible that such specific features are not present in the version of grep used by the OP.

So as long as we don't know what environment the OP has and what version of which tool he can use I suggest to stick to the common features present in all versions of the tools used.

This again nicely illustrates the Un*x philosophy.

It's easy to underestimate the power of combining pipes and redirection. As an instructive example, The Unix Shell As a 4GL [Schaffer-Wolf] shows that with these facilities as a framework, a handful of simple utilities can be combined to support creating and manipulating relational databases expressed as simple textual tables.

http://www.catb.org/~esr/writings/taoup/html/ch07s02.html#plumbing

The Un*x philosophy is IMO tremendously helped by installing GNU versions of tools (in addition to, not replacing, your OS's versions).
ysth
+4  A: 

This will work:

grep 'SEARCHTERM' server.log | grep -Ev 'PHHIABFFH|Stats'
catwalk
For versions of grep that support `-E, --extended-regexp`.
You can drop the `-E` if and quote the `|` like this: `grep -Ev 'PHHIABFFH\|Stats'`
Chen Levy
I decided to use this. The first grep normally will return around 5000 to 10000 lines, and so having multiple runs of grep cost me a second or two.
Brian
@brian, if you want to use the fastest in terms of speed of execution, use the awk solution. There's no need to invoke 2 greps. Even the shell version would run a tad faster than 2 greps.
@levislevis85, 2 greps are actually faster, at least on my box. example(yields 0.3s for grep and 0.6s for awk): seq 1000000 >o; time grep 1 o|grep -Ev '2|3' > /dev/null; time awk '$0 !~ /2|3/
catwalk
@levislevis85: yes, you are going to have a very hard time finding a line-oriented program like awk that will beat the highly IO-optimized grep
ysth
A: 

If simple means just one command with more args ...

awk '$0 !~ /PHHIABFFH|Stats/ && /SEARCHTERM/' server.log
The MYYN
you beat me to it: but it should be $0 not $1. Otherwise this is as "simple" as you're going to get.
Zac Thompson
to the down voter, don't down vote for fun.
A: 

you can just use the shell

while read -r line
do
   case "$line" in
    *"Stats"*|*"PHHIABFFH"*) continue;;
    *"SEARCHTERM"* ) echo "$line";;
   esac
done < "file"
A: 

I would have just done this:

grep 'SEARCHTERM' server.log | grep -v -e 'PHHIABFFH' -e 'Stats'
ysth
calling 2 greps is unnecessary.
@levislevis85: just for kicks, assume SEARCHTERM ends up selecting 1% of the original lines; how would you do it faster than this?
ysth