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

What am I missing??
my $sql = "'XXXX-ax1-d.ett.amrs.bankofamerica.com','UAT','AMRS','AMS', +'','YYYY','ZZZZ',,,,"; print "$sql\n"; $sql =~ s/,,/,NULL,/g; print "$sql\n"; $sql =~ s/,,/,NULL,/g; ## I dont know why this is needed twice print "$sql\n";
OUTPUT:
$ ./test.pl 'XXXX-ax1-d.ett.amrs.bankofamerica.com','UAT','AMRS','AMS','','YYYY',' +ZZZZ',,,, 'XXXX-ax1-d.ett.amrs.bankofamerica.com','UAT','AMRS','AMS','','YYYY',' +ZZZZ',NULL,,NULL, 'XXXX-ax1-d.ett.amrs.bankofamerica.com','UAT','AMRS','AMS','','YYYY',' +ZZZZ',NULL,NULL,NULL,

Replies are listed 'Best First'.
Re: Global in RE not working as expected?
by AnomalousMonk (Archbishop) on Jan 24, 2018 at 15:50 UTC

    Because  s/,,/,NULL,/g replaces and consumes commas in pairs. E.g.:

    c:\@Work\Perl\monks>perl -wMstrict -le "my $s = 'abcdef'; ;; $s =~ s{ \w \w }{ print qq{$&}; ',NULL,'; }xmsge; print qq{'$s'}; " ab cd ef ',NULL,,NULL,,NULL,'
    Try something like:
    c:\@Work\Perl\monks>perl -wMstrict -le "my $s = qq{'XXXX-ax1-d.ett.com','AMRS','AMS','','YYY','ZZ',, , ,}; print qq{'$s'}; ;; $s =~ s{ (?<= ,) \s* (?= , | \z) }{NULL}xmsg; print qq{'$s'}; " ''XXXX-ax1-d.ett.com','AMRS','AMS','','YYY','ZZ',, , ,' ''XXXX-ax1-d.ett.com','AMRS','AMS','','YYY','ZZ',NULL,NULL,NULL,NULL'


    Give a man a fish:  <%-{-{-{-<

Re: Global in RE not working as expected?
by hippo (Archbishop) on Jan 24, 2018 at 15:51 UTC

    You need to use a lookahead instead. Without that each s/,,/whatever/ eats up 2 commas so the 2nd and 3rd comma in a row in the original text are never tested. Here's a solution:

    my $sql = "'XXXX-ax1-d.ett.amrs.bankofamerica.com','UAT','AMRS','AMS', +'','YYYY','ZZZZ',,,,"; print "$sql\n"; $sql =~ s/,(?=,)/,NULL/g; print "$sql\n";
Re: Global in RE not working as expected?
by choroba (Cardinal) on Jan 24, 2018 at 15:52 UTC
    Because:
    'XXXX-ax1-d.ett.amrs.bankofamerica.com','UAT','AMRS','AMS','','YYYY',' +ZZZZ',,,, + ^ matches here 'XXXX-ax1-d.ett.amrs.bankofamerica.com','UAT','AMRS','AMS','','YYYY',' +ZZZZ',NULL,,, + ^ matches here

    The comma after NULL is part of the match and replacement, so the next match starts after it.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Global in RE not working as expected?
by haukex (Archbishop) on Jan 24, 2018 at 15:53 UTC

    When the regex engine replaces the first ",," with ",NULL,", it does not continue matching inside of the replacement string, so the only thing left for it to match and replace is the last two ",,". One solution is zero-width Lookaround Assertions:

    my $sql = ",,,,"; print "<$sql>\n"; # <,,,,> $sql =~ s/(?<=,)(?=,)/NULL/g; print "<$sql>\n"; # <,NULL,NULL,NULL,>

    However, editing SQL like this seems like it might not be the best approach. If you're using DBI you should use placeholders, and if you're generating SQL, I recommend you look into modules that do that, like SQL::Abstract (example).

    (Update: AnomalousMonk, hippo, and choroba were a little faster :-) )

Re: Global in RE not working as expected?
by paisani (Acolyte) on Jan 24, 2018 at 16:07 UTC
    Learn something new every day! Cool beans, as they used to say in the 60's. Thanks.
      ... can I also have a single RE that would add a NULL after that last comma?

      Sure. The one given here does it; others, too, in other replies, I think.

      Update: Wuf...?!? paisani changed the post while I replied. Whatever...


      Give a man a fish:  <%-{-{-{-<

        Yeah, sorry about that. Sometimes realization sinks in late. :-)