Git Grep Multiple Words on Multiple Lines
Asked Answered
C

3

15

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 ?

Careless answered 18/5, 2016 at 15:42 Comment(1)
Maybe something like git grep -l word1 | xargs git grep -l word2... May need to play around with it more if any of your file names contain whitespace or other oddities...Schindler
L
11

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.

Lorislorita answered 18/5, 2016 at 20:11 Comment(0)
B
6

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
Bisulfate answered 24/5, 2022 at 9:41 Comment(1)
or git grep -zl word1 | xargs -0 git grep -l word2Eudemonia
E
0

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.

Eudemonia answered 13/1, 2023 at 10:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.