Is there a grep-like utility that will return a variable number of context lines? I need to search through source code for occurrences of a particular function and get back the function plus its arguments, even if they're split across multiple lines. E.g. if I search for "proto_tree_add_text" I want back
proto_tree_add_text(subtree, tvb, curr_offset, 1, "%s : Reserved", bigbuf);
and
proto_tree_add_text(tree, tvb, offset, payload_len, "Payload");
equally. I _don't_ want the extra one-size-fits-all fluff returned by GNU grep's "-A" flag.
I'm sure I've done this before with sed, but I can't find it. I thought I might challege my sed skills and whip it up, but I got lazy and wrote it in perl (though I'm sure you could do this yourself if you wanted). Just make sure to escape your "start" and "end" arguments for use in regexes.
Example: cgrep.pl -s 'some_function(' -e ');' -f ./some_source
Caveat: Wouldn't work if you had wierd nesting, like: some_function( ... some_function( ... ); ... ); you'd just match: some_function( ... some_function( ... );
#!/usr/bin/perl -w
#Usage # cgrep.pl -s <start pattern> -e <end pattern> -f <input file>
use strict; use Getopt::Long;
my($start, $end, $file);
GetOptions( "start=s" => $start, "end=s" => $end, "file=s" => $file, );
die "All arguments are required" unless ($start && $end && $file);
if( defined( $file ) && -e $file ) { open( IN, $file ) || die "couldn't open file"; }
my @matches; my $matching; my $linecount = 0;
while( my $line = readline *IN) { $linecount++; if( $line =~ /($start.*)/ ) { $matching = "true"; push( @matches, $linecount . ": " . $1 . "\n" );
# in some cases our whole pattern will be in one line... if( $1 =~ /$end/){ $matching = "0"; } next; }
if( $matching ) { if( $line =~ /(.*$end)/ ) { push( @matches, $linecount . ": " . $1 . "\n" ); $matching = "0"; } else { push( @matches, $linecount . ": " . $line ); } } }
print @matches;
On Tuesday 21 June 2005 09:49, Gerald Combs wrote:
Is there a grep-like utility that will return a variable number of context lines? I need to search through source code for occurrences of
The problem statement is modeled by a fairly simple 5 state machine. Here's a very simple Ruby implementation of the state machine. It takes one argument which is the name of the function and searchable input on STDIN for grep-like behavior. It only returns the entire function header lines. Case sensitive, of course.
#!/usr/bin/ruby
more_state = false
while $stdin.gets() if more_state == false and $_.include?( ARGV[0] ) puts $_ more_state = true if ! ( $_.include?("{") or $_.include?(";") ) elsif more_state == true puts $_ more_state = false if ( $_.include?("{") or $_.include?(";") ) end end
On Tuesday 21 June 2005 11:32, Jason Clinton wrote:
The problem statement is modeled by a fairly simple 5 state machine. Here's
Someone asked what a state machine is. In a nutshell, it's a way of listing all the states that a program might be in during its lifetime and how you move from one state to another.
And for anyone that decides to give their favorite language a crack at this, there are actually 2 states and 5 possibilities that you must consider:
Given that a Boolean variable named "THERE'S_MORE_LINES" exists then
THERE'S_MORE_LINES = false and line doesn't match criteria THERE'S_MORE_LINES = false and line matches and has header terminator THERE'S_MORE_LINES = false and line matches and doesn't have header terminator THERE'S_MORE_LINES = true and line doesn't have header terminator THERE'S_MORE_LINES = true and does have header terminator
The initial state is THERE'S_MORE_LINES = false.
So if you want to draw this out draw two circles which represent the value of THERE'S_MORE_LINES and write True in one and False in the other. Then draw an arrow line for each of the 5 possibilities above. If the possibility doesn't change THERE'S_MORE_LINES, then draw an arrow line that starts at either the True or False node and loops around back in to it.
For instance, if the case is "THERE'S_MORE_LINES = false and line matches and doesn't have header terminator" then you draw a line from false to true.
If it's "THERE'S_MORE_LINES = false and line matches and has header terminator" then you draw a loop from false to false.
CS people tend to draw an arrow line labeled "Start" pointing to the initial state of the machine.
Then, you pick your favorite language and ensure that the code handles all the lines (possibilities) in your drawing.
if I search for "proto_tree_add_text" I want back
proto_tree_add_text(subtree, tvb, curr_offset, 1, "%s : Reserved", bigbuf);
and
proto_tree_add_text(tree, tvb, offset, payload_len, "Payload");
equally. I _don't_ want the extra one-size-fits-all fluff returned by GNU grep's "-A" flag.
how about this untested one-liner:
perl -ne 'BEGIN{undef $/};print /(proto_tree_add_text\s*(.+?;\s+\n)/gs'
i think the semicolon will work as a search terminator, ymmv of course