I want to find files that have "abc" AND "efg" in that order, and those two strings are on different lines in that file. Eg: a file with content:
blah blah..
blah blah..
blah abc blah
blah blah..
blah blah..
blah blah..
blah efg blah blah
blah blah..
blah blah..
Should be matched.
You can do that very easily if you can use Perl.
You can do that with a single regular expression too, but that involves taking the entire contents of the file into a single string, which might end up taking up too much memory with large files. For completeness, here is that method:
While the sed option is the simplest and easiest, LJ's one-liner is sadly not the most portable. Those stuck with a version of the C Shell will need to escape their bangs:
This unfortunately does not work in bash et al.
The filepattern
*.sh
is important to prevent directories to be inspected. Of course some test could prevent that too.The
searches maximum 1 matching and returns (-n) the linenumber. If a match was found (test -n ...) find the last match of efg (find all and take the last with tail -n 1).
else continue.
Since the result is something like
18:foofile.sh String alf="abc";
we need to cut away from ":" till end of line.Should return a positive result if the last match of the 2nd expression is past the first match of the first.
Then we report the filename
echo $f
.If you need both words are close each other, for example no more than 3 lines, you can do this:
Same example but filtering only *.txt files:
And also you can replace
grep
command withegrep
command if you want also find with regular expressions.With silver searcher:
similar to ring bearer's answer, but with ag instead. Speed advantages of silver searcher could possibly shine here.
you can use grep incase you are not keen in the sequence of the pattern.
example
grep -l
will find all the files which matches the first pattern, and xargs will grep for the second pattern. Hope this helps.