Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Grepping a File

by carcassonne (Pilgrim)
on Apr 16, 2006 at 17:29 UTC ( [id://543666]=perlquestion: print w/replies, xml ) Need Help??

carcassonne has asked for the wisdom of the Perl Monks concerning the following question:

Folks,

Using a C header file as source, I'd like to get the define string for a certain number. This has to be done several times, so I'd like to load the file in memory and get the result from memory in order to save the overhead associated with external system calls.

For obtaining the same thing at the console prompt I use:

cat defines.h | grep 42 | awk '{print $2}'

This will return 'UNIVERSE_ANSWER' for instance, when the C header file has the following entry:

#define UNIVERSE_ANSWER 42

Now, if I use Perl's grep on a buffer that contains the file it returns either 1 (scalar context) or the whole file (array context):

my $result = grep ('/28/', $buff);

my @result = grep ('/28/', $buff);

I was expecting at least the line, so I could do a split on it after.

One could do a loop on the buffer with a regex, but surely there must be a technique in Perl that makes this easy and moreover, optimized. Hence, this is my query.

Any suggestions welcomed !

2006-04-17 Retitled by planetscape, as per Monastery guidelines
Original title: 'Grepping memory ?'

Replies are listed 'Best First'.
Re: Grepping a File
by rhesa (Vicar) on Apr 16, 2006 at 17:55 UTC
    well, grep operates on a list, so you'd better apply it to the lines directly. Instead of slurping the file into a scalar buffer, why not put it in an array in the first place?
    use strict; use warnings; open my $fh, '<', 'defines.h' or die $!; my @lines = <$fh>; my @all_28s = grep /28/, @lines; my @all_42s = grep /UNIVERSE_ANSWER/, @lines;
Re: Grepping a File
by graff (Chancellor) on Apr 16, 2006 at 18:00 UTC
    Well, if your "$buf" contains the entire content of some file (because you have read the file using "slurp" input mode), of course grep is going to return the whole thing.

    If you want the specific line that contains the given value, either treat the file data as an array of lines, or else change how you are looking for the target string:

    # (no need to change how $buff is assigned) # option 1: my ( $result ) = grep( /28/, split( /\n/, $buff )); my $target = ( split( / /, $result )[1]; # get 2nd token from matched + line # option 2: my ( $target ) = ( $buff =~ /(\S+)\s+28\n/ );

    In the latter approach, if " 28\n" occurs more than once in the file, only the first occurrence is captured to $target.

Re: Grepping a File
by mickeyn (Priest) on Apr 17, 2006 at 05:28 UTC
    Hi,

    Try this -

    First, tie your file to an array and 'grep' the lines you wish into a new array.
    (that's your "cat defines.h | grep 42")

    Second, print the field you wish from each line.
    (that's your "awk '{print $2}'")

    use Tie::File; tie @array, 'Tie::File', "defines.h" || die; my @lines = grep /42/, @array; untie @array; foreach (@lines) { split; print $_[1]; # = AWK's $2 }

    BTW, your awk code can be written without the use of pipes, grep & cat (and will probably work faster this way):

    awk '/42/ {print $2}' defines.h

    Enjoy,
    Mickey

Re: Grepping a File
by jpeg (Chaplain) on Apr 16, 2006 at 19:26 UTC
    You're using grep correctly. Your expectations of what it should return are incorrect. When I find my code returning unexpected results, I check perldoc. That would have helped you.

    Secondly, I suggest that if you're going to search through the contents of a file, read the lines of the file into an array or use a while loop. I find that I'm iterating over lines of a file much much more than I slurp the contents into a variable.

    --
    jpg
Re: Grepping a File
by parv (Parson) on Apr 16, 2006 at 20:21 UTC

    Going by the subject alone, memgrep appreared in mind.

    (Then the body defalted my expectation to find a Perl solution.)

    Edited by planetscape - removed pre tags, replaced with <p></p> tags

    Apr 17, 2006. Well, title change of OP renders my above comment useless.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://543666]
Approved by blokhead
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (2)
As of 2024-04-26 05:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found