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

Problem with substr

by newbie1991 (Acolyte)
on May 14, 2013 at 15:50 UTC ( [id://1033511]=perlquestion: print w/replies, xml ) Need Help??

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

Hi, I have a list of names that I am trying to clean up. Some of them have ".replaced" after the name, which I am trying to remove. The code I am using is this :

$name = substr $name, 0, rindex( $name, q{replaced} );
The line works just fine for the names that are followed by the "replaced", however, the last letter of the name gets cut off if the name is not followed by "replaced". e.coli.replaced becomes e.coli (which is fine), but z.mays becomes z.may (which isn't). How can I fix this?

Replies are listed 'Best First'.
Re: Problem with substr
by marto (Cardinal) on May 14, 2013 at 16:00 UTC

    "e.coli.replaced becomes e.coli (which is fine)

    It doesn't. With your code it becomes "e.coli.".

    "but z.mays becomes z.may (which isn't)."

    Don't assume what rindex returns, try this for your test case:

    print rindex( $name, q{replaced} );

    A simpler way of doing this would be:

    my $name = "e.coli.replaced"; $name =~ s/.replaced//;

    Should you actually wish the outcome to be as you specified and not what your code actually does.

    Update: Fixed typo

    Update 2: Dang, this is a must read, catches my mistake.

      $name =~ s/.replaced//;

      Note that the  . (dot) in the quoted regex is the metacharacter for the operation "match any character except a newline" and as such will occasionally fail to do what newbie1991 wants. I suggest something like
          $name =~ s/\.replaced//;
      in which the dot is escaped to remove its meta-magic and make it match only a lowly period.

      >perl -wMstrict -le "my $name = 'e.coliXreplaced'; $name =~ s/.replaced//; print qq{'$name'}; " 'e.coli'
      Switching to s/// did the trick. Thanks :)
Re: Problem with substr
by kennethk (Abbot) on May 14, 2013 at 16:03 UTC
    If rindex has no matches, it returns -1. If substr gets a negative OFFSET, it "starts that far back from the end of the string". The correct approach here would be to test the result of rindex, and only modify if the number is non-negative:
    if ((my $index = rindex( $name, q{.replaced})) > -1 ) { $name = substr $name, 0, $index; }

    Note as well that you have an off-by-one error on your replacement, which I have fixed by adding '.' to your string.

    Update: AnomalousMonk caught that the rindex was in the LENGTH argument, not the OFFSET argument.

    If LENGTH is negative, leaves that many characters off the end of the string.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Log In?
Username:
Password:

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

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

    No recent polls found