Home > Net >  perl regex to replace $ with $$ unless $ followed by one of ^ @ ( $
perl regex to replace $ with $$ unless $ followed by one of ^ @ ( $

Time:11-15

I'd like to replace $ characters with $$ unless $ is followed by one of ^, @, (, or $.

For example given:

$(bar) $@ $$.z $^.zh $(foo) $foo $bar 

I'd like:

$(bar) $@ $$.z $^.zh $(foo) $$foo $$bar

I have a brutal hack way of doing this (replacing the patterns I don't want to get modified with a temporary probably unique garbage sequence), replacing everything left, and then undoing my temporaries.

my $var = ' $(bar) $@ $$.z $^.zh $(foo) $foo $bar ';
                                                                                        
my $d = '$';
my $at = '@';                                                                               
   
$var =~ s/\$\(/<<<<DDDDBBBB>>>>/g;
$var =~ s/\$\@/<<<<DDDDAAAA>>>>/g;
$var =~ s/\$\^/<<<<DDDDCCCC>>>>/g;            
$var =~ s/\$\$/<<<<DDDDDDDD>>>>/g;
$var =~ s/\$/$d$d/g;                   
$var =~ s/<<<<DDDDBBBB>>>>/$d(/g;
$var =~ s/<<<<DDDDAAAA>>>>/$d$at/g;                                
$var =~ s/<<<<DDDDCCCC>>>>/$d^/g;
$var =~ s/<<<<DDDDDDDD>>>>/$d$d/g;
                                                                                                                                                            
print "$var\n";   

This works, but it's butt ugly. My naive one liner attempt was:

my $var = ' $(bar) $@ $$.z $^.zh $(foo) $foo $bar ';
print "$var\n";
my $d = '$';
$var =~ s/\$([^\@\(\$\^])/$d$d$1/g;
print "$var\n";

but this does not handle the $$ correctly. The first match of $$ fails to replace as desired, but the '$.' part of '$$.' character sequence gets replaced, giving:

$(bar) $@ $$$.z $^.zh $(foo) $$foo $$bar 

I could do a hybrid:

my $var = ' $(bar) $@ $$.z $^.zh $(foo) $foo $bar ';

my $d = '$';
my $at = '@';

print "$var\n";

$var =~ s/\$\$/<<<<DDDDDDDD>>>>/g;
$var =~ s/\$([^\@\(\^])/$d$d$1/g;
$var =~ s/<<<<DDDDDDDD>>>>/$d$d/g;

print "$var\n";

but that's still ugly, just not quite so bad. Is there a way of doing this replacement with a single perl regex, perhaps using assertions or lookarounds?

CodePudding user response:

I'd like to replace $ characters with $$ unless $ is followed by one of ^, @, (, or $.

Use a look ahead.

s/ \$ (?! [\^\@(\$] ) / '$$' /xeg

but this does not handle the $$ correctly.

It does according to what you said you wanted.

But you appear appear to have an unstated requirement to ignore $ characters if the number of $ characters immediately preceding it is odd.

An easy way to handle that is by simply replacing $$ in addition to $ not followed by ^/@/).

s/ \$ (?: \$ | (?! [\^\@\(] ) ) / '$$' /xeg
  • Related