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

Consider for example a string $str="xyabcyxyxyxyxy" and a string $chompstr="xy". I would like to produce a new string which as many copies of $chompstr chopped off at the end as possible - in the example case, the result would be "xyabcy". What would be a good way (in whatever measurement of the word "good") to solve this?

My first attempt was to use the following regexp:

$str =~ s/($chompstr)*\z//;
I used \z instead of $, because we might legally chomp something like "#\n". This works most of the time, but it does of course not work if $chompstr contains characters which have special meanings in a regexp. So I was thinking about the following possibilities: Both solutions are certainly possible, but maybe there is an easier way to do it, or maybe someone knows a module which already offers this functionality...

-- 
Ronald Fischer <ynnor@mm.st>

Replies are listed 'Best First'.
Re: Chomping Frenzy question
by moritz (Cardinal) on Jul 10, 2008 at 13:09 UTC
    $str =~ s/(?:\Q$chompstr\E)+\z//;

    Or use the quotemeta builtin.

    By the way you'd have to use chomp and not chop, because the latter unconditionally chops off the last character, whereas chomp removes $/.

      $str =~ s/(?:\Q$chompstr\E)+\z//;

      Wouldn't this also fail if $chompstr contained \E ?

      Or use the quotemeta builtin.

      This is nice! I had used this function a few years ago, but meanwhile forgotten it.

      By the way you'd have to use chomp and not chop

      Of course, you are right. I was too careless when sketching my solutions...

      -- 
      Ronald Fischer <ynnor@mm.st>
        Wouldn't this also fail if $chompstr contained \E ?

        No, it's magic:

        use strict; use warnings; my $str = 'foo\E**** <- this is a syntax error'; if ("foo" !~ m/\Q$str\E/){ print "No syntax error\n"; } __END__ No syntax error

        If the quoting had stopped by the embedded \E, you'd get the Nested quantifiers in regex error.

        Wouldn't this also fail if $chompstr contained \E ?

        No. That confused me when I first heard of \Q..\E too.

        • \Q..\E doesn't prevent interpolation.
        • \E isn't special in interpolated strings. It matches the two characters. "\" and "E"
        • $ don't trigger interpolation in interpolated strings. It matches end of lines.
Re: Chomping Frenzy question
by poolpi (Hermit) on Jul 10, 2008 at 13:57 UTC
    my $s = "xyabcy*+!*+!*+!*+!*+!*+!"; $s =~ y/*+!//d;


    From perlop :
    if you want to use variables either in the SEARCHLIST or REPLACEMENTLIST , you must use an eval()

    hth,
    PooLpi

    'Ebry haffa hoe hab im tik a bush'. Jamaican proverb
      $s =~ y/*+!//d;

      This would replace all the characters in $s, not only those in the end, and it would replace them in any sequence - so this is not useable in my situation.

      -- 
      Ronald Fischer <ynnor@mm.st>
        $s =~ y/*+!//d;
        This would replace all the characters in $s, not only those in the end, and it would replace them in any sequence - so this is not useable in my situation.

        No, it wouldn't (remove any character).
        It removes any occurence of the characters '*', '+' and '!' (it's a use of the transliterate operator tr/// (same as y///). It doesn't care about the position of the characters.

        $ perl -e 'my $s = "xyabcy*+!*+!*+!*+!*+!*+!"; $s =~ y/*+!//d; print +$s, $/;' xyabcy $ perl -e 'my $s = "*+!xyabcy*+!*+!*+!*+!*+!*+!"; $s =~ y/*+!//d; pri +nt $s, $/;' xyabcy $

        I don't think, that tr/// or y/// can help you with your chomp problem.

        update: minor changes in text (... remove any char...)