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

Hi, I have a small problem.In a cgi form i am taking input in two text boxes corresponding to hours of the day
enteries could be like:
00 and 23 (all day)
04-08
then i have to grep for all the entries in a file that have been logged in those hours.
fileformat
hourminute/min/avg/max
0422/56/67/89
for this i want to generate a grep statement on the fly. can anyone help me with this i was thinking of
foreach ($starttim..$endtime) { grep formed here }

can i have some sort of a grep ^04|^05|^06|^07|^08
or does it have to be
cat file | grep -e "^04" -e "^05" (beginning with hour in the file so as not to match minutes)
but i cannot come up with a fast logic. Is there better way then above? thanks

Replies are listed 'Best First'.
Re: Generating a grep command at run time
by Thelonius (Priest) on May 22, 2003 at 06:10 UTC
    Do you actually need to generate a grep command or is it okay to actually perform the search with Perl itself?

    Also, there is no reason to do cat file | grep pattern, you can just do grep pattern file. There is a small difference if you are searching more than one file, since grep pattern file1 file2 shows the file names on the output, whereas cat file1 file2 | grep pattern does not.

    Okay, if you really need to generate a grep command, I would do it like this:

    #!perl -w use strict; my $starttim = 4; my $endtime = 9; my $pattern = "^(" . join("|", map { sprintf "%02d", $_ } $starttim .. $endtime ) . ")"; my $cmd = "grep -e '$pattern' file"; print "cmd = $cmd\n";
    The join function is great when you need to have things between the elements of list. Much easier than coding a loop.
      There is a small difference if you are searching more than one file, since grep pattern file1 file2 shows the file names on the output, ...
      Not if you use '-h'. Anyway, I would probably do the whole thing in perl, unless speed was really that much of an issue. And if it is (saving minutes or hours), then you might be able to do:
      perl -e ' # Generate pattern and file names... exec 'grep', '-e', $pattern, @files; ' [args...]
Re: Generating a grep command at run time
by chimni (Pilgrim) on May 22, 2003 at 10:42 UTC
    Thanks t,
    but the above does not work.
    grep -e '^04' is ok but grep -e '^(04|05)' does not work. (HP-UX 11)
    Secondly wouldnt a grp pattern file be faster than reading the file line by line and pattern matching like this  $_ =~ /^(04|05). Thanks for your input again
      chimni,
      HPUX does things a little differently when it comes to grep. You are going to want to change the grep to an egrep without the -e option and it should work fine. As an alternative, you could leave it as grep and change the -e to a -E option. See the local man page on grep to see why this works.

      Cheers - L~R

      Secondly wouldnt a grp pattern file be faster than reading the file line by line and pattern matching like this $_ =~ /^(04|05).

      I doubt it. Grep has to read the entire file in, too, so you're not saving anything in disk access. There might be some speedup if grep on your system is implemented to read normally instead of line-by-line. Really, from a speed point of view, it will all come down to whichever program has a more optimized regex engine. In practice, the extra expense of just executing grep will probably make up for any lost speed.

      Further, I wouldn't worry about speed at all. The pure-Perl soultion will work just fine. Relying on external programs like this is generally a Bad Thing (tm). There are many problems with using external programs, not the least of which is potential security issues. It also tends to make less maintainable code.

      ----
      I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
      -- Schemer

      Note: All code is untested, unless otherwise stated

        hardburn,
        I have to completely disagree with you. The *nix utility grep is a compiled C program specifically designed for a single task. I worked very hard to modify tcgrep to be nearly as fast as the *nix grep. This only worked because of my very specific problem and still failed miserably in a general sense.

        I am not sure what you mean by read normally instead of line-by-line. As best as I can tell, both Perl and grep see the file as a data stream. They read data into a buffer, they then process that buffer "line-by-line" by terminating on the newline character. The speed difference would be if the default buffer size is different - i.e. actual less physical reads as they only go back out to disk when the buffer is empty.

        I agree that Perl offers all the functionality of the *nix grep and more, so resorting to using it for any reason other than raw speed seems like a bad idea. I would say that the reason not to use it isn't because of security or maintainability even though these are very valid points. To me, it is because of portability. This isn't even a matter of Win32 vs *nix portability - as can be seen in this thread.

        Cheers - L~R