Reputation: 79
I am having trouble figuring out a very specific use case for Grep and Regex. I have searched a lot and can't seem to find the answer.
I want to run Grep recursively from within a root directory which contains directories for hundreds of different programs. I want the output to print to a text file and list the file names of all the files which match some regex. Specifically, here's what I need to do in english:
find all files that contain the text [stringA] AND ["stringB"] OR ['stringB'] and print the file paths for each of these files to an output text file with some context added. For the two stringB pieces, the quotes are important and I only want to find files that have stringB with single or double quotes around it. In other words,
all files that contain stringA with no quotes and stringB with either single or double quotes.
Any help is appreciated, thanks!
Edit: Sorry for asking a terrible question :)
I have done some research and have figured out part of it. I have figured out the regex for finding the string I am looking for. The actual string is "ATA". To find this globally, case-insensitive, and with either type of quotes around it with some or no whitespace on either side of the string, we can use:
/['"]\s*ATA\s*['"]/gi
The first string I need to also find is a function call: call wflnkmod( and the regex for that is:
/call\swflnkmod\(/gi
Now I just need to figure out how to search a file and ensure that it has an instance of each of these in it, then figure out the grep command to use to search all files recursively and print them to an output file!
Upvotes: 2
Views: 2795
Reputation: 67467
for AND
search it's better to chain grep
s, OR
can be handled.
Assume we are looking for words cat
and "ata"
or 'ata'
. If you're only interested in the filenames, not the actual matches...
grep -wilm1 cat file* | xargs grep -wilEm1 "'ata'|\"ata\""
file1
file2
searches for the full word match -w
(not substrings), exits after first match -m1
and ignores cases (-i
). The OR
requires -E
flag. -l
prints the filenames only.
here are the files used for testing.
==> file1 <==
cat
fat hat "ata"
==> file2 <==
cat fat hat 'ata'
==> file3 <==
cat fat hat ata
==> file4 <==
category fat hat ata
Upvotes: 1
Reputation: 191
Should do the trick (<dir>
needs to be replaced with the directory to search in):
grep -r -i -l "stringA" <dir> | xargs grep -i -l -E "'stringB'|\"stringB\""
The above line searches for stringA
first. The resulting list of files is piped into xargs
and the specified command (grep -i -l -E "'stringB'|\"stringB\""
) is invoked with the additional parameters provided through stdin (the list of files, that contain stringA
).
grep
options:
-r, --recursive
(self explanatory)-i, --ignore-case
search case insensitive-l, --files-with-matches
only print filename of files that match the
given pattern-E
interpret pattern as extended regular expressionThe two main issues with the expressions you've tried are:
[]
. []
lets you define a character set, e.g. [abcd]
matches one of specified characters."
), double quotes inside the quoted string need to be escaped: \"
yields a "
in a quoted string. If you're not quoting your expression at all, (
needs to be escaped as well.Upvotes: 3