Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

regex to rename last _ with ,

by Anonymous Monk
on Sep 11, 2014 at 13:01 UTC ( [id://1100291]=perlquestion: print w/replies, xml ) Need Help??

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

I am trying to rename the last _ with a , but not sure how to do that.
Here is what I have so far-

my @flist = qw' 1st-device-CA_Eth.0/1 2nd-device-TX_Gig.1/1 '; print "@flist\n"; for my $file (@flist) { $file =~ s{\_[^_]+$}{, }; print "$file\n"; }
Output:
1st-device-CA_Eth.0/1 2nd-device-TX_Gig.1/1 1st-device-CA, 2nd-device-TX,

Now, how do I get the rest of the info back after that (,)? Please help.

Replies are listed 'Best First'.
Re: regex to rename last _ with ,
by choroba (Cardinal) on Sep 11, 2014 at 13:07 UTC
    If you know how to replace the first underscore with a comma, just add reverse:
    $file = reverse $file; $file =~ s/_/,/; $file = reverse $file;

    To get back what's after the inserted comma, the following should work:

    $file =~ s/_([^_]*)/,$1/; my $rest = $1;
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      it was that easy!.... thank you.
Re: regex to rename last _ with ,
by AnomalousMonk (Archbishop) on Sep 11, 2014 at 13:18 UTC

    Not sure just what you're doing since you don't post in  <code> ... </code> tags, but I think I would use a look-ahead:

    c:\@Work\Perl\monks>perl -wMstrict -le "my @flist = qw( 1st-device-CA_Eth.0/1 2nd-device_TX_Gig.1/1 3rd_device_MO_Gig.1/1 ); ;; for my $s (@flist) { print qq{'$s'}; $s =~ s{ _ (?= [^_]* \z) }{,}xms; print qq{'$s'}; print ''; } " '1st-device-CA_Eth.0/1' '1st-device-CA,Eth.0/1' '2nd-device_TX_Gig.1/1' '2nd-device_TX,Gig.1/1' '3rd_device_MO_Gig.1/1' '3rd_device_MO,Gig.1/1'

      Thank you for the code.

      s{ _ (?= ^_* \z) }{,}xms;

      I would appreciate if someone could explain what it's doing for each part.
        +----------------------------- In the scalar $s (interpreted as a str +ing), | +--------------------- if you find an _ (underscore) | | +----------------- that's followed by 0 or more of anythi +ng but an _ (underscore) | | | and then the end-of-string, | | | + -- replace it with a , (comma). | | | | V V V V $s =~ s{ _ (?= [^_]* \z) }{,}xms;

        Update: See "Look-Around Assertions" in the Extended Patterns of perlre.

        (And the use of  <code> ... </code> tags would still be much appreciated.)

        Another Update: If you have Perl version 5.10+, another way (see  \K in Extended Patterns):

        c:\@Work\Perl\monks>perl -wMstrict -le "use 5.010; ;; my @flist = qw( 1st-device-CA_Eth.0/1 2nd-device_TX_Gig.1/1 3rd_device_MO_Gig.1/1 ); ;; for my $s (@flist) { print qq{'$s'}; $s =~ s{ .* \K _ }{,}xms; print qq{'$s'}; print ''; } " '1st-device-CA_Eth.0/1' '1st-device-CA,Eth.0/1' '2nd-device_TX_Gig.1/1' '2nd-device_TX,Gig.1/1' '3rd_device_MO_Gig.1/1' '3rd_device_MO,Gig.1/1'

Re: regex to rename last _ with ,
by Anonymous Monk on Sep 11, 2014 at 13:10 UTC

    Use () to catch the end portion: m{ _ ([^_]+) $ }x. Then use the portion captured in replacement via $1. And, RTFM.

Re: regex to rename last _ with ,
by dmitri (Priest) on Sep 13, 2014 at 16:14 UTC
    This can be done without advanced features like lookaheads:
    s/_([^_]*)$/,$1/
    I am not sure if I prefer this or reverse solutions. If strings are large and there are many underscores in a string, I'd use reverse.
      This can be done without advanced features like lookaheads ...

      It seems strange to me to see a regex lookahead (or, in general, a look-around) assertion described as 'advanced'. It's as if one had said "X can be done without advanced features like lexical variables or hard references." Present, I believe (although I haven't taken the trouble to confirm this), since version 5.0, this is a feature I consider part of the 'baseline' definition of Perl 5.

      Whenever I allude to a feature like the  \K regex operator or the defined-or operator, I feel obliged to mention that is is only available beginning with Perl version 5.whatever and I make an effort to highlight its presence in a code example by including a  use 5.x; statement at the beginning, but I always assume that Perl 5 is the baseline for discussion nowadays. (Does anyone use a version 4 interpreter anymore?)

      This is only idle curiosity, but can you say why you consider regex look-around assertions advanced?

        A couple of reasons. First, I can never remember the exact syntax of the look-around assertions, so I have to perldoc perlre each time I use one. This makes it advanced in my mind. I guess this is highly subjective, so your point is taken.

        Second, the more features are used in a regular expression, the more there is to translate when you want to use it in another tool. Doing without look-ahead brings the RE to a lower common denominator, so to speak.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (2)
As of 2025-07-14 20:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.