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

Hi, I want to use the replace only the first comma(,) from every line in a file. How can I do that? For the moment I have this

$string1 = "ABC,XYZ PERL IS, AWESOME, INNIT"; $string1 =~ s/(,[^,]*),/$1/gi; print "The resulting value is : $string1 \n";
which only gives me the output as ABC,XYZ PERL IS AWESOME, INNIT But I am expecting- ABC,XYZ PERL IS AWESOME INNIT

Replies are listed 'Best First'.
Re: Replace only selected characters
by hbm (Hermit) on Oct 14, 2011 at 18:39 UTC

    You describe replacing only the first comma, but then expect exactly the opposite: "ABC,XYZ PERL IS AWESOME INNIT". It seems you want to remove all commas except for the first.

    Try this. It "looks behind" for a comma, without consuming it; then matches (and stores) up to a comma; then replaces; and repeats.

    s/(?<=,)([^,]*),/\1/g;
      That worked!. Thanks for the solution. I learned something today :)
      Hi, Im struggling to Use this against a csv file with several lines of lines like this which needs formatting.
      open(FILE, "<ABC.csv"); @lines = <FILE>; print @lines; print $lines[1]; close(FILE); foreach ($lines) { $lines = ~ s/(?<=,)([^,]*),/\1/g; print("$lines \n"); }
      what am I doing wrong now :(
        foreach ($lines) { $lines = ~ s/(?<=,)([^,]*),/\1/g; print("$lines \n"); }

        In addition to the fact that the scalar  $linesdoesn't appear to be defined anywhere (you are using warnings and strictures, aren't you?), the statement
            $lines = ~ s/(?<=,)([^,]*),/\1/g;
        should probably be
            $lines =~ s/(?<=,)([^,]*),/$1 /g;
        (the  =~ operator should have no space between = and ~, use  $1 instead of  \1 in the replacement string, there should actually be a space somewhere in the replacement string if you want to replace a ',' with a space). I would suggest something like (untested):

        foreach my $line (@lines) { $line =~ s/(?<=,)([^,]*),/$1 /g; print("$line \n"); }

        Update: After further inspection of the OP and replies, it appears that rohanan wants every ',' after the first replaced with the empty string rather than with a space. So (still untested):
            $line =~ s/(?<=,)([^,]*),/$1/g;

        Hi,

        'foreach ($lines) {' -
        should this be 'foreach (@lines) {' ?

        And so on

        J.C.

Re: Replace only selected characters
by herveus (Prior) on Oct 14, 2011 at 18:04 UTC
    Howdy!

    Instead of answering directly, I ask you to consider what the "g" and "i" flags do. Think carefully about everything your search expression actually says. Do the parts work together the way you want them to?

    Try carefully applying your replace manually. Alternately, express more clearly what you are trying to accomplish with your replace.

    yours,
    Michael
Re: Replace only selected characters
by johngg (Canon) on Oct 14, 2011 at 22:21 UTC

    Another, possibly simpler, way might be to split the line on commas then glue it all together again, joining using a comma the first element to the remaining elements that have been joined using an empty string.

    knoppix@Microknoppix:~$ perl -E ' > $l = q{abc,def,ghi,jkl,mno}; > say $l; > @e = split m{,}, $l; > $l = join q{,}, $e[ 0 ], join q{}, @e[ 1 .. $#e ]; > say $l;' abc,def,ghi,jkl,mno abc,defghijklmno knoppix@Microknoppix:~$

    I hope this is helpful.

    Cheers,

    JohnGG

Re: Replace only selected characters
by AnomalousMonk (Archbishop) on Oct 16, 2011 at 02:56 UTC

    Another, not necessarily better, way to "replace every x after the first with y" (needs Perl 5.10+):

    >perl -wMstrict -le "for my $s ( 'ABC,XYZ PERL,, IS, AWESOME, INNIT', ',ABC,XYZ PERL,, IS, AWESOME, INNIT,', ',,ABC,XYZ PERL,, IS, AWESOME, INNIT,', ) { print qq{ in: '$s'}; ;; (my $t = $s) =~ s{ (?: \A [^,]* , (*SKIP)(*FAIL))? , }{}xmsg; print qq{out: '$t'}; print ''; } " in: 'ABC,XYZ PERL,, IS, AWESOME, INNIT' out: 'ABC,XYZ PERL IS AWESOME INNIT' in: ',ABC,XYZ PERL,, IS, AWESOME, INNIT,' out: ',ABCXYZ PERL IS AWESOME INNIT' in: ',,ABC,XYZ PERL,, IS, AWESOME, INNIT,' out: ',ABCXYZ PERL IS AWESOME INNIT'
Re: Replace only selected characters
by johngg (Canon) on Oct 17, 2011 at 13:21 UTC

    Yet another way using a global look-ahead match and pos to find the commas then substr to erase all but the first, working back from the end of the string.

    knoppix@Microknoppix:~$ perl -E ' > $l = q{abc,def,ghi,jkl,mno}; > say $l; > push @p, pos $l while $l =~ m{(?=,)}g; > substr $l, $_, 1, q{} for reverse @p[ 1 .. $#p ]; > say $l;' abc,def,ghi,jkl,mno abc,defghijklmno knoppix@Microknoppix:~$

    Cheers,

    JohnGG

      Interesting. I wondered why the look-ahead (and not just /,/g), but now I see.

      Note that you can do this:

      push @p, pos $l while $l =~ m{(?=,)}g;

      As:

      push @p, @- while $l =~ /,/g;
        Thanks everyone..Some very good methods