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

Hi all, How do I append a string to another string that beginning with a alphabet while keeping the symbols as is in this example?

my $path = "XX.YY.ZZ"; my $s = "(ABC | (~dEf & hIJ)) & ~LMn";
Expected output : (XX.YY.ZZ.ABC | (~XX.YY.ZZ.dEf & XX.YY.ZZ.hIJ)) & ~XX.YY.ZZ.LMn; Any help is appreicated, thanks!

Replies are listed 'Best First'.
Re: Appending strings
by toolic (Bishop) on Sep 16, 2015 at 23:56 UTC
    s///g
    use warnings; use strict; my $path = "XX.YY.ZZ"; my $s = "(ABC | (~dEf & hIJ)) & ~LMn"; $s =~ s/([a-z]+)/$path.$1/gi; print "$s\n"; __END__ (XX.YY.ZZ.ABC | (~XX.YY.ZZ.dEf & XX.YY.ZZ.hIJ)) & ~XX.YY.ZZ.LMn

    Verilog equation?

      works great and yes it's verilog thank you
      There are strings that I don't need appending the $path, such as "else" "if" "1'b0", is there a way to add this to the expression or do I have to split ' ' and check each string? Also, how do I treat "ABC_DEF" "b_C_D_E" as one word and append $path only to the beginning of the string? Thanks

        Including _ and ignoring some keywords...

        #!/usr/bin/perl # http://perlmonks.org/?node_id=1142266 use strict; use warnings; my $path = "XX.YY.ZZ"; my $s = "(ABC | (~dEf & hIJ)) & ~LMn if foo while bar"; my %ignore = map { $_, $_ } qw( if while for ); (my $answer = $s) =~ s/(\w+)/$ignore{$1} || "$path.$1"/ge; print "$answer\n";
Re: Appending strings
by AnomalousMonk (Archbishop) on Sep 17, 2015 at 03:53 UTC

    Another variation:

    c:\@Work\Perl\monks>perl -wMstrict -le "my $path = 'XX.YY.ZZ'; my ($ignore) = map qr{ (?: $_) (?! [[:alpha:]]) }xms, join q{ | }, qw(if while for) ; ;; my $s = '(ABC | (~dEf & hIJ)) & ~LMn if form while i'; ;; my $expected = '(XX.YY.ZZ.ABC | (~XX.YY.ZZ.dEf & XX.YY.ZZ.hIJ)) & ~XX +.YY.ZZ.LMn if XX.YY.ZZ.form while XX.YY.ZZ.i'; print qq{expected: '$expected'}; ;; $s =~ s{ (?<! [[:alpha:]]) (?= [[:alpha:]]) (?! $ignore) } {$path.}xmsg; print qq{ got: '$s'}; $s eq $expected or die 'FAILED'; print 'a-ok'; " expected: '(XX.YY.ZZ.ABC | (~XX.YY.ZZ.dEf & XX.YY.ZZ.hIJ)) & ~XX.YY.ZZ +.LMn if XX.YY.ZZ.form while XX.YY.ZZ.i' got: '(XX.YY.ZZ.ABC | (~XX.YY.ZZ.dEf & XX.YY.ZZ.hIJ)) & ~XX.YY.ZZ +.LMn if XX.YY.ZZ.form while XX.YY.ZZ.i' a-ok
    (Long lines: Beware linewrap.)

    Update: Just took another look at Re^2: Appending strings and realized solution above doesn't cover "1'b0" or "ABC_DEF". These could be included, but I'm sure that wouldn't be the end of it. Yeah, a real Verilog parser looks like the best bet.


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

Re: Appending strings
by johngg (Canon) on Sep 17, 2015 at 10:08 UTC

    Perhaps you could use positive and negative look-arounds with pos to find where you want to insert $path. and then work back along the string inserting with the 4-argument form of substr.

    use strict; use warnings; use 5.014; my $path = q{XX.YY.ZZ}; my $str = q{(ABC | (~dEf & hI_J)) & ~LMn if ~xYz}; # Make a compiled regex of an alternation of the terms to exclude. # my $rxExcl = do { my @excl = qw{ if else 1'b0 }; local $" = q{|}; qr{(?:@excl)}; }; my @posns; push @posns, pos $str while $str =~ m{(?x) # Use extended regex syntax (?<! [A-Za-z_] ) # Match at a point not preceded by # letters or underscore (?= [A-Za-z_] ) # And which is followed by letters # or underscore (?! $rxExcl ) # But not followed by any our terms # to exclude }g; substr $str, $_, 0, qq{$path.} for reverse @posns; say $str;

    Outputs

    (XX.YY.ZZ.ABC | (~XX.YY.ZZ.dEf & XX.YY.ZZ.hI_J)) & ~XX.YY.ZZ.LMn if ~X +X.YY.ZZ.xYz

    I hope this is useful.

    Update: Added comment above $rxExcl creation and comments to the string matching regex to clarify what it is doing.

    Cheers,

    JohnGG

      Hi, I added "end" to the excl list and the string beginning with endxxx is not getting substituted. To exclude "end" but not "end" that's followed by strings or symbol or numbers, do I do excl = qw{ end\b ) ? thanks

        If I have understood correctly what you require, use the "word boundary" asserstion (\b), see perlre.

        use strict; use warnings; use 5.014; my $path = q{XX.YY.ZZ}; my $str = q{(ABC | (~dEf & hI_J & endxxx)) & ~LMn if ~xYz end}; # Make a compiled regex of an alternation of the terms to exclude. # my $rxExcl = do { my @excl = qw{ if else 1'b0 end }; local $" = q{|}; qr{(?x) (?: @excl ) \b}; }; my @posns; push @posns, pos $str while $str =~ m{(?x) # Use extended regex syntax (?<! [A-Za-z_] ) # Match at a point not preceded by # letters or underscore (?= [A-Za-z_] ) # And which is followed by letters # or underscore (?! $rxExcl ) # But not followed by any our terms # to exclude }g; substr $str, $_, 0, qq{$path.} for reverse @posns; say $str;

        The output.

        (XX.YY.ZZ.ABC | (~XX.YY.ZZ.dEf & XX.YY.ZZ.hI_J & XX.YY.ZZ.endxxx)) & ~ +XX.YY.ZZ.LMn if ~XX.YY.ZZ.xYz end

        I hope this is what you want.

        Cheers,

        JohnGG

Re: Appending strings
by Anonymous Monk on Sep 16, 2015 at 23:57 UTC
    #!/usr/bin/perl # http://perlmonks.org/?node_id=1142266 use strict; use warnings; my $path = "XX.YY.ZZ"; my $s = "(ABC | (~dEf & hIJ)) & ~LMn"; print $s =~ s/(\w+)/$path.$1/gr, "\n";
      I tried it and it says : syntax error at t line 80, near "s/(\w+)/$path.$1/gr" Execution of t aborted due to compilation errors.
        #!/usr/bin/perl # http://perlmonks.org/?node_id=1142266 use strict; use warnings; my $path = "XX.YY.ZZ"; my $s = "(ABC | (~dEf & hIJ)) & ~LMn"; (my $answer = $s) =~ s/(\w+)/$path.$1/g; print "$answer\n";

        Tweaked for older perls.

Re: Appending strings
by doofus (Acolyte) on Sep 17, 2015 at 21:33 UTC
    Thank you all for your suggestions. I'll spend some time to study them.