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

I'm trying to remove/replace all occurrences of a semicolon, except for the very last. I've been messing around with various regular expressions, but I just can't quite get it right.

Take this example for instance:

my $string = "I have multiple ; in my string; however I want to keep t +he last one;"

I need a regular expression that'll remove/substitute all the ; except the last one.

$string =~ s/<regex>//; print "$string\n"; I have multiple in my string however I want to keep the last one;

Replies are listed 'Best First'.
Re: Quick regex substitution question
by stevieb (Canon) on May 29, 2015 at 14:16 UTC

    Here's a look-ahead assertion that ought to do what you need. It looks for a ';' with anything after it between another ';', and replaces the first one. When it hits the last one, there's no more characters before another ';', so it has nothing else to substitute.

    EDIT: It does not hit end-of-line as I previously stated. This example will leave any chars following the last ';', if there's no other ';' before EOL.

    #!/usr/bin/perl use warnings; use strict; my $string = "I have; in my string; replace all but last one;"; $string =~ s/;(?=.*;)//g; print $string;

    Output:

    ./r.pl I have in my string replace all but last one;

    -stevieb

      For the sake of people in the future reading this thread, you can use look ahead/behind to split() something, and retain the thing you split on.

      The following split() splits on either whitespace or nothing with a '.' before it. The whitespace, if present, is thrown away, but the dot is retained within each split() element.

      #!/usr/bin/perl my $string = "I have. In my string.Replace all but last one."; @parts = split(/(?<=\.)\s*/, $string); print "$_\n" for @parts; __END__ ./split.pl I have. In my string. Replace all but last one.

      -stevieb

      Sweet, that looks like it did what I'm looking for. Thanks for the help!

Re: Quick regex substitution question
by toolic (Bishop) on May 29, 2015 at 14:13 UTC
    I'm not sure how to do it in a single regex, but here's one way to delete all except the last semicolon (even if it is not the last character in the string):
    use warnings; use strict; my $string = "I have multiple ; in my string; however I want to keep t +he last one;"; my $count = $string =~ tr/;//; $string =~ s/;// for 1 .. $count-1; print "$string\n"; __END__ I have multiple in my string however I want to keep the last one;
Re: Quick regex substitution question
by hdb (Monsignor) on May 29, 2015 at 14:11 UTC

    You need to search for "look-ahead assertion" in the docs.

    As I am no master of this I would do $string =~ s/;(.)/$1/g; assuming that the semikolon is the last character in the string.

      Yeah I've been trying to implement a look-ahead assertion, but it's not working. I been trying something like this...

      $string =~ s/\;(?!\;$)//g;

      I thought it would find all occurrences of ; but not the last one followed by end-of-line, but it's not working. There's something I don't understand.

        Part of your problem is your attempt to escape the semicolons. They're NOT end_of_statement markers to Perl or its regex engine when inside a quoted string. You may also want to read about using '!' as a negation.