You can do it using -v
(for --invert-match
) option of grep as:
grep -v "unwanted_word" file | grep XXXXXXXX
grep -v "unwanted_word" file
will filter the lines that have the unwanted_word
and grep XXXXXXXX
will list only lines with pattern XXXXXXXX
.
EDIT:
From your comment it looks like you want to list all lines without the unwanted_word
. In that case all you need is:
grep -v 'unwanted_word' file
I understood the question as "How do I match a word but exclude another", for which one solution is two greps in series: First grep finding the wanted "word1", second grep excluding "word2":
grep "word1" | grep -v "word2"
In my case: I need to differentiate between "plot" and "#plot" which grep's "word" option won't do ("#" not being a alphanumerical).
Hope this helps.
word1
.
xnoty() { grep -v "$2" | grep "$1" }
) so you don't have to remember the construction.
If your grep
supports Perl regular expression with -P
option you can do (if bash; if tcsh you'll need to escape the !
):
grep -P '(?!.*unwanted_word)keyword' file
Demo:
$ cat file
foo1
foo2
foo3
foo4
bar
baz
Let us now list all foo
except foo3
$ grep -P '(?!.*foo3)foo' file
foo1
foo2
foo4
$
grep -v -P
also works without negation in regular expression.
!
". Thank you thank you thank you! That's what I wanted!
(?!.*unwanted_word)keyword
only excludes lines where the unwanted_word
starts after the keyword
(possibly overlapped). To exclude any line that contains the unwanted_word
, regardless of its position relative to the keyword
, use ^(?!.*unwanted_word).*\Kkeyword
.
The right solution is to use grep -v "word" file
, with its awk
equivalent:
awk '!/word/' file
However, if you happen to have a more complex situation in which you want, say, XXX
to appear and YYY
not to appear, then awk
comes handy instead of piping several grep
s:
awk '/XXX/ && !/YYY/' file
# ^^^^^ ^^^^^^
# I want it |
# I don't want it
You can even say something more complex. For example: I want those lines containing either XXX
or YYY
, but not ZZZ
:
awk '(/XXX/ || /YYY/) && !/ZZZ/' file
etc.
grep -P
solution on big files.
grep -P
means using Perl regexp, so loading that package is going to be way more expensive than a normal grep
.
Invert match using grep -v:
grep -v "unwanted word" file pattern
grep provides '-v' or '--invert-match' option to select non-matching lines.
e.g.
grep -v 'unwanted_pattern' file_name
This will output all the lines from file file_name, which does not have 'unwanted_pattern'.
If you are searching the pattern in multiple files inside a folder, you can use the recursive search option as follows
grep -r 'wanted_pattern' * | grep -v 'unwanted_pattern'
Here grep will try to list all the occurrences of 'wanted_pattern' in all the files from within currently directory and pass it to second grep to filter out the 'unwanted_pattern'. '|' - pipe will tell shell to connect the standard output of left program (grep -r 'wanted_pattern' *) to standard input of right program (grep -v 'unwanted_pattern').
The -v
option will show you all the lines that don't match the pattern.
grep -v ^unwanted_word
I excluded the root ("/") mount point by using grep -vw "^/"
.
# cat /tmp/topfsfind.txt| head -4 |awk '{print $NF}'
/
/root/.m2
/root
/var
# cat /tmp/topfsfind.txt| head -4 |awk '{print $NF}' | grep -vw "^/"
/root/.m2
/root
/var
I've a directory with a bunch of files. I want to find all the files that DO NOT contain the string "speedup" so I successfully used the following command:
grep -iL speedup *
Success story sharing
-v 'unwanted_word' --after N
doesn't help because it INCLUDES the line and N lines after.-v
or--invert-match
select non-matching lines. In your casegrep -v 'unwanted_word' file
orgrep --invert-match 'unwanted_word' file
.sun
, except when it issunrise
,grep sun|grep -v sunrise
skips line that contain bothsun
andsunrise
at once, that is not what I want.grep -P 'sun(?!rise)'
is much better.-E
. e.g.grep -v -E "unwanted_pattern_in_regex" file