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

#!/usr/bin/perl # I have a piece like this that i cant get right... # # if i get a filename like this - $count contains a two # digit number that is incrimented throughout the program # to process the next file $tempfile=`ls -l |awk '{ print $9 }' |grep $count` ; # # say the $tempfile is something like # nov_11th_word_txt.txt # and i just wanted to strip the '.txt' off it ...? what do i do? point me to the light :) DerrickM

Replies are listed 'Best First'.
Re: thanks
by chromatic (Archbishop) on Oct 25, 2000 at 08:39 UTC
    Here's a quick regex:

    $tempfile =~ s!\.[^\.]+$!!;

    That matches everything after and including the last literal period in the filename, and gets rid of it.

RE: thanks, i'm new. rtfm right? :)
by extremely (Priest) on Oct 25, 2000 at 08:41 UTC
    Assuming you have the filename in a variable:
    # variable has a return on the end, possibly $variable= "file_name_text.txt\n"; chomp $variable; # removes the return but won't remove non-whitespace +. $variable =~ s/\.txt$//; # now variable has no ".txt" on the end.

    Look at the documentation for regular expressions (perldoc perlre) too learn more about that last line. I'd like to help more but your explanation was kinda scattered so I'm not sure what you are really asking. I do know that backtick line looks real evil to me. I think you need a "\" in front of the "$9" so that it won't freak out perl but I'm not sure.

    --
    $you = new YOU;
    honk() if $you->love(perl)

Re: thanks
by runrig (Abbot) on Oct 25, 2000 at 08:44 UTC
    Don't bother with the system call(s):
    opendir
    readdir
    closedir
    grep
    and maybe: File::Basename (ok, maybe not)
    and you can strip off a fixed string like '.txt' with substr even though a regex looks cooler (and I admit is more self-documenting) as others have shown. I don't get whether you just want to process '.txt' files or you want to strip extentions off of all files. I'd build a list of all the files (grep'ing just the '.txt' files?) then grep the $count from the list each time, or order the list by the implied $count in the files, and process the list in order.
Re: thanks
by strredwolf (Chaplain) on Oct 25, 2000 at 16:46 UTC
    Don't use awk. Instead, try this.

    opendir(DIR,"."); @d=readdir(DIR); closedir(DIR); foreach $j (@d) { $_=$j; $template=/^.*\.[^.]+/ if(/$count/); }
    Error checking is left to the exersize of the student, as well as accomidating for two or more hits of /$count/. Besides, the less you spawn a shell, the better (unless it's a quick hack);

    --
    $Stalag99{"URL"}="http://stalag99.keenspace.com";

      The assignment of $_ to $j seems redundant to me. Just write it like this:
      foreach (@d) { $template=/^.*\.[^.]+/ if(/$count/); }
      $_ is already filled with whatever is in @d...
      You can parse the files in the directory with a structure like this, instead of using opendir/readdir/closedir:
      my @files = (); foreach (<*$count*>) { s/\.[^.]*$//; push @files, $_; }

      Not sure what you needed to do with the files, but you might do that inside the loop as well. I'm not sure exactly how <*> works internally, but it's definitly better than doing a system() call that relies on ls, awk, and grep (even if those are fine tools). I find it cool, yet strangely disturbing, that you can interpolate the variable $count into the <...> directory listing.

      -Ted
        <*> (file globbing) used to spawn a csh process (and used to do some other horrible thing on Windows), but now (as of 5.6?) uses File::Glob. I still avoid it, because (open|read|close)dir with grep provides better file and pattern matching capabilities. And maybe I just find the syntax ambiguous (I confuse it with reading lines of a filehandle), which is maybe just my own prejudice. I'm curious as to what others think of file globbing vs. readdir...
RE: thanks, i'm new. rtfm right? :)
by daevt (Initiate) on Oct 26, 2000 at 23:02 UTC
    My solution would be to use spilt(), because L love split().
      try something like "($tempflie, $garbage) = split(/./);"
      this should split $_ at any "." into $
      tempfile and $garbage. I beleive that if there isn't a "."
      it doesn't split anything up.
      I can't believe someone mod'ed this down without pointing out why...

      If you want to split on the period char you need to do it one of these ways...

      split(/\./); # or split(/[.]/);

      The period is special in regular expressions, like the one split uses to find separators. You just told split that every character was a legal separator and if you do that you get a big fat nada...

      --
      $you = new YOU;
      honk() if $you->love(perl)