Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Grabbing file prefixes with Reg Exp

by nysus (Parson)
on May 13, 2001 at 20:13 UTC ( [id://80047]=perlquestion: print w/replies, xml ) Need Help??

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

The following line:

my @audiofiles = grep { /([^\.]+)\.ram/i } readdir DH;

...gives me audiofile1.ram, audiofile2.ram, audiofile3.ram, etc. into the array.

What I'd like to get is audiofile1, audiofile2, audiofile3 instead, with no file extensions. Shouldn't the parentheses in my reg exp be doing this for me? What am I missing?

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar";
$nysus = $PM . $MCF;

Replies are listed 'Best First'.
Re: Grabbing file prefixes with Reg Exp
by MrNobo1024 (Hermit) on May 13, 2001 at 20:19 UTC
    grep returns the whole filenames, not just a parenthesized group. I think what you want is my @audiofiles = map { /([^\.]+)\.ram/i ? $1 : () } readdir DH;
      You so smart! That did the trick. Guess I gotta learn the "map" function now...thanks!

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar";
      $nysus = $PM . $MCF;

Re: Grabbing file prefixes with Reg Exp
by tomhukins (Curate) on May 13, 2001 at 20:25 UTC

    The parentheses grab into $1, but grep works with $_.

    Also, there is a problem with your regular expression. It will match any file containing .ram, not just files ending in this extension.

    Be aware that as you are matching case insensitively, your regexp will also match files containing the string .RAM or .rAm. I'm assuming this is okay. Try:

    my @audiofiles = grep { s/\.ram$//i } readdir DH;
      Good catch and an interesting solution. Muchos gracias.

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar";
      $nysus = $PM . $MCF;

Re: Grabbing file prefixes with Reg Exp
by japhy (Canon) on May 13, 2001 at 23:51 UTC
    Allow me to point out some places of improvement:
    • to see if a string ends in something, you must anchor it with \z, \Z, or $
    • match what you need; this is wasteful: /.*\.foo$/
    • using /i is sometimes wasteful, especially for a few characters
    That said, I offer:
    my @files = map s/\.[Rr][Aa][Mm]$// ? $_ : (), readdir DH;
    Maybe you think those character classes look ugly, and maybe the difference is minimal, but in a case like this, I think it's a wise investment. Also, you may wish to use a different ending anchor in place of $.

    japhy -- Perl and Regex Hacker
      using /i is sometimes wasteful, especially for a few characters

      <counteropinion>

      Unless the regexp is going to be in a performance-sensitive area of code, the performance gained by using character classes instead of /i is going to be outweighed by the readability hit.

      To my eye, it's easier (albeit only slightly so) to grasp the intent of   my @files = map s/\.ram$//i ? $_ : (), readdir DH; than it is to grasp   my @files = map s/\.[Rr][Aa][Mm]$// ? $_ : (), readdir DH; When hardware performance isn't an issue, optimize for wetware (readability).

      Didn't you mean to make this a grep? :)
      my @files = grep s/\.ram$//i , readdir DH;
      Also, I agree with dws regarding the readability of the character classes, and believe you're altogether mistaken regarding the performance issue:
      use strict; use Benchmark qw(cmpthese); my $strorig = 'yabadabadooo this bud is a buda fora youa'; cmpthese (-3, { mod => sub { my $str = $strorig; $str =~ m/.*BUD.*/i }, class => sub { my $str = $strorig; $str =~ m/.*[Bb][Uu][Dd].*/ }, }); ## Results (under ActiveState 5.6) ## Rate class mod class 347719/s -- -15% mod 408606/s 18% --
         MeowChow                                   
                     s aamecha.s a..a\u$&owag.print
        Yes, it was meant to be a grep() -- I took the map() and modified it, and forgot to change it.

        And I guess I'm mistaken about char classes. I was using information from MRE, I think, which is now oldish, so Perl has probably made some changes.

        japhy -- Perl and Regex Hacker
Re: Grabbing file prefixes with Reg Exp
by Kanji (Parson) on May 13, 2001 at 20:29 UTC

    Try using a substitution (s///) instead so that you directly modify what grep returns.

    my @auditofiles = grep { s/\A([^.]+)\.ram\z/$1/i } readdir DH;

        --k.


      Any reason for using the \A ... \z assertions instead of the commonplace ^ ... $ metachars? I believe that's the first I've seen those two used. More generally, is there a difference, outside of multiline-matching mode?
         MeowChow                                   
                     s aamecha.s a..a\u$&owag.print
        \z only matches at the end of the string, but $ can match before a newline at the end. Unless you're using multiline mode, \A and ^ are the same.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (3)
As of 2024-04-19 20:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found