http://qs321.pair.com?node_id=320366

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

I have a directory with about thirty text files. I was trying to find an acronym in the directory, but I didn't really remember what it was (other than it was a four letter word starting with M).

I tried a few one-liners, but none of them worked. Since I was just trying to find something really quickly, I decided to punt and just write a script to do what I wanted.

Now I'm trying to learn more about one-liners (I don't have any experience with them) just so I can handle this situation a bit better next time it comes up.

I should also note that I'm doing this from a Windows command prompt.

Here are some of the one-liners that I tried (in a for loop, single file example shown here):

And finally, here's the subroutine that actally did what I wanted:

my @files = <*.txt>; undef $/; foreach (@files) { open ( FH, $_ ); my $txt = <FH>; close ( FH ); while ( $txt =~ m/(M[A-Z]{3}) /gs ) { print " $1\n"; } }

Is there a way to do something like this as a one-liner? If so, then can I incorporate the glob into the one-liner? Thanks for your help.

janitored by ybiC: Prepend tile wit "One-liner" for searchability

Replies are listed 'Best First'.
Re: One-liner for Matching a Regex in a Directory of Files
by Paladin (Vicar) on Jan 10, 2004 at 20:18 UTC
    You were close with your second one-liner. From perldoc perlrun you'll notice that -p wraps your code in:
    LINE:
      while (<>) {
        ...             # your program goes here
      } continue {
        print or die "-p destination: $!\n";
      }
    
    which prints everyline by default, while -n wraps your code in:
    LINE:
      while (<>) {
        ...             # your program goes here
      }
    
    Note, there is no automatic printing here. So if you use -n instead of -p in your second one-liner, you would have what you want.
Re: One-liner for Matching a Regex in a Directory of Files
by allolex (Curate) on Jan 10, 2004 at 20:56 UTC
    a four letter word starting with M

    In that case, you should also be using the carat to tell your regex that the letter "M" is found just after the beginning of the filename.

    m/^M[A-Z]{3}/

    So you get:

    perl -le'foreach ( <*.txt> ) { print if /^M[A-Z]{3}/ }'

    --
    Allolex

      Sorry, I didn't mean to imply that that M was at the beginning of the file. Each text file is a separate essay and the acronym was just a word in the body of the file.

      I combined ideas from both tips to come up with the following (semi-Perl) solution. Thanks for your help Paladin and allolex.

      for %a in (*.txt) do @perl -ne "if (m/ (M[A-Z]{3}) /) { print qq($1\n); }" %a

Re: One-liner for Matching a Regex in a Directory of Files
by davido (Cardinal) on Jan 11, 2004 at 06:00 UTC
    I happen to like the following one liner because its output is the entire line that matches, which provides context.

    perl -ne "print qq/$. : $_\n/ if m/\bM[A-Z]{3}\b/" testfile.txt

    In that one liner, any line that contains a four letter capitalized word starting with M, the whole line will print, so you can get a good idea of where it appears in the file. Also, the line number within the file is printed for added clarity.

    The regex uses the \b "word boundry" assertion at both sides of the M[A-Z]{3} construct, to ensure that four and only four letters will trigger a match.


    Dave