Ashraf Bashir
Ashraf Bashir

Reputation: 9804

Git Grep Multiple Words on Multiple Lines

I want to git grep the files which has two pre-specified words (if both exist, i.e. ANDing), assume these two words are word1 and word2

I tried

git grep -e 'word1' --and -e 'word2'

And also I tried

git grep 'word1'.*'word2'

but both retrieve the results only if word1 and word2 are on the same line, and the second one does not retrieve if word2 comes first in the line, which is something that I don't want.

I want to retrieve the files, even if the two words are not on same line (I am not sure how many lines separates them, and the order is not important; any order should be fetched).

Is this possible ?

Upvotes: 16

Views: 7030

Answers (3)

CervEd
CervEd

Reputation: 4243

Since git-grep matches patterns per line, like grep, the way to achieve this is by breaking up the problem.

First, find all files with word1, in those files, find word2.

Basically git grep -l word1 | xargs git grep word2.

A more thorough example could be something like

git grep -z --name-only word1 |
  xargs -0 git grep -z --name-only word2 |
  xargs -0 grep -zPl 'word1.*\n{0,5}.*word2'

This finds all files where word2 follows word1, separated by at most 5 lines.

Upvotes: 0

EoghanM
EoghanM

Reputation: 26924

You can do

git grep -l word1 |xargs grep -l word2

The -l option lists the file name instead of the matching line.

This is necessary to feed them into the second right hand side grep (xargs is a utility piping function)

I'm guessing you'd be happy with -l on the right hand side also as otherwise it would show the lines which match word2 with no reference to word1.


Just seeing @twalberg's comment now which recommends a similar solution.

Which reminds me, if you are having trouble with filenames, you need a few extra arguments:

git grep -zl word1 |xargs -0 grep -l word2

Upvotes: 6

alpert
alpert

Reputation: 4655

Searching multi-line with git-grep is not possible.

Taken from: http://git.661346.n2.nabble.com/bug-git-grep-P-and-multiline-mode-td7613900.html

Yes, and deliberately so, to avoid having to think about things like "how would a multi-line match interact with 'grep -n'?"

We behave as if we feed each line of the contents one line at a time to the matching engine that is chosen by the -P/-E/-G/-F options, so this limitation is unlikely to change.

Upvotes: 11

Related Questions