Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

replace first occurance if it doesn't already match

by ddrew78 (Beadle)
on Mar 10, 2017 at 16:21 UTC ( #1184183=perlquestion: print w/replies, xml ) Need Help??

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


I am in need of a rather unique solution. I have a string such as V12345:name_test or V12345_name_testWhat I need is that, if there is a "_" after the numbers, to replace it with ":", but if the ":" already exists, any subsequent "_" should remain as is. So "V12345_name_test" should be changed to "V12345:name_test", but "V12345:name_test" should remain unchanged. I've tried several different ways to 'sed' it, but can't get it to work correctly. As usual, any wisdom is greatly appreciated.

Replies are listed 'Best First'.
Re: replace first occurance if it doesn't already match
by toolic (Bishop) on Mar 10, 2017 at 16:26 UTC
    This works on the input you provided. It looks for the 1st digit followed by an underscore and replaces _ with :. Refer to s///
    use warnings; use strict; while (<DATA>) { s/(\d)_/$1:/; print; } __DATA__ V12345:name_test V12345_name_test
      Worked like a champ. Very much appreciated.
Re: replace first occurance if it doesn't already match
by hippo (Bishop) on Mar 10, 2017 at 16:34 UTC

    Something like this perhaps?

    #!/usr/bin/env perl use strict; use warnings; use Test::More; my @rows = ( { have => 'V12345:name_test', want => 'V12345:name_test' }, { have => 'V12345_name_test', want => 'V12345:name_test' }, ); plan tests => scalar @rows; for my $row (@rows) { my $out = $row->{have}; $out =~ s/(\d)_/$1:/; is ($out, $row->{want}); }

    How well this regex works depends on how true your sample dataset is. You can amend @rows and the regex until you have covered all the possibilities you require. See also How to ask better questions using Test::More and sample data.

    Addendum: I see that toolic has used precisely the same substitution in his answer while I was constructing this. That bodes well for it as a solution to your specific question.

Re: replace first occurance if it doesn't already match
by haukex (Bishop) on Mar 10, 2017 at 16:32 UTC

    The following works for the very limited test cases you've provided. Because I wasn't sure whether by "if there is a "_" after the numbers" you meant "immediately after the numbers", or just "somewhere after the numbers", I invented two more test cases, but I don't know if they represent what your strings actually look like. If you could provide more test cases, we could be of more help.

    use warnings; use strict; use Test::More; sub subst { my $x = shift; $x =~ s/\d+[^_:]*\K_/:/; return $x; } is subst("V12345_name_test"), "V12345:name_test"; is subst("V12345:name_test"), "V12345:name_test"; is subst("V12345x_name_test"), "V12345x:name_test"; is subst("V12345x:name_test"), "V12345x:name_test"; # ... more test cases needed here! done_testing;

    Update: Added the other two test cases. Added some more explanation.

Re: replace first occurance if it doesn't already match
by thanos1983 (Parson) on Mar 10, 2017 at 16:39 UTC

    Heelo ddrew78,

    Something like that?

    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my @array = ("V12345:name_test", "V12345_name_test"); my @final = (); foreach my $str (@array) { if ($str =~ /[\w]+:/) { my @elements = split /:/, $str, 0; my $tmp = $elements[0] . "_" . $elements[1]; push @final, $tmp; } next; } print Dumper \@final; __END__ $ perl $VAR1 = [ 'V12345_name_test' ];

    There are other ways I am sure but just an idea.

    Hope this helps.

    Seeking for Perl wisdom...on the process of learning...not there...yet!

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2022-05-23 20:40 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (82 votes). Check out past polls.