Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I grep for entire, possibly wrapped, lines of code?

When searching code for strings, I constantly run into the problem that I get meaningless, context-less results. For example, if a function call is split across 3 lines, and I search for the name of a parameter, I get the parameter on a line by itself and not the name of the function.

For example, in a file containing

...
  someFunctionCall ("test",
                    MY_CONSTANT,
                    (some *really) - long / expression);

grepping for MY_CONSTANT would return a line that looked like this:

                    MY_CONSTANT,

Likewise, in a comment block:

/////////////////////////////////////////
// FIXMESOON, do..while is the wrong choice here, because
// it makes the wrong thing happen
/////////////////////////////////////////

Grepping for FIXMESOON gives the very frustrating answer:

// FIXMESOON, do..while is the wrong choice here, because

When there are thousands of hits, single line results are a little meaningless. What I would like to do is have grep be aware of the start and stop points of source code lines, something as simple as having it consider ";" as the line separator would be a good start.

Bonus points if you can make it return the entire comment block if the hit is inside a comment.

I know you can't do this with grep alone. I also am aware of the option to have grep return a certain number of lines of context. Any suggestions on how to accomplish under Linux? FYI my preferred languages are C and Perl.

I'm sure I could write something, but I know that somebody must have already done this.

Thanks!

like image 541
NXT Avatar asked Apr 22 '10 04:04

NXT


People also ask

How do you grep with surrounding lines?

You can use option -A (after) and -B (before) in your grep command. Try grep -nri -A 5 -B 5 .

How do you grep multiple lines after a match?

Use the -A argument to grep to specify how many lines beyond the match to output. And use -B n to grep lines before the match. And -C in grep to add lines both above and below the match!

What does the V flag do for grep?

grep -v “pattern” file. The -v flags invert the search results, as it displays those strings in file. txt which do not contain pattern .


2 Answers

You can use pcregrep with the -M option (multiline matching; pcregrep is grep with Perl-compatible regular expressions). Something like:

pcregrep -M ";*\R*.*thingtosearchfor*\R*.*;.*"
like image 169
Will Hayworth Avatar answered Nov 15 '22 18:11

Will Hayworth


Here's an example using awk.

$ cat file
blah1
blah2
  function1 ("test",
                    MY_CONSTANT,
                    (some *really) - long / expression);

function2( one , two )
blah3
blah4

$ awk -vRS=")" '/function1/{gsub(".*function1","function1");print $0RT}' file
function1 ("test",
                    MY_CONSTANT,
                    (some *really)

the concept behind: RS is record separator. by setting it to ")", then every record in your file is separated by ")" instead of newline. This make it easy to find your "function1" since you can then "grep" for it. If you don't use awk, the same concept can be applied using "splitting" on ")".

like image 36
ghostdog74 Avatar answered Nov 15 '22 19:11

ghostdog74