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

Hi Perlmonks!, you just helped me out very fine in an old post, but now there is a change which leads me to a new question. I found out that replacing of a single word or word combinations sometimes does not work although I mark them for not beeing interpreted. In this case I have a txt document which includes '+#' . Perl is not able to replace this two signs by '$coin22'. With other signs it just works fine. How can I improve my program to not interpret the strings he wants to read in at all? Here my skript:

#!/usr/bin/perl -w #use strict; my $SCU = 'C:/Users/user/Desktop/a.txt'; open (FILE, '<', $SCU) or die "$SCU File not found : $!"; my @lines = <FILE>; close (FILE); my $A= '+#'; my $B= '$coin22'; my @newlines; push @newlines, s/$A/$B/rg for @lines; open (FILE, '>', $SCU) or die "Could not open file $SCU: $!"; print FILE @newlines; close (FILE);
Thank you very much in advance! Best regards

Replies are listed 'Best First'.
Re: seek and replace for exceptional characters
by toolic (Bishop) on Sep 23, 2013 at 17:20 UTC
Re: seek and replace for exceptional characters
by MidLifeXis (Monsignor) on Sep 23, 2013 at 17:45 UTC

    You could also change your push line to:

    push @newlines, s/\Q$A\E/$B/rg for @lines;
    (the \E is optional in this case, as the quoted variable is the last thing in the RE) to handle the quotemeta within the search/replace itself. See perlre for more information.

    Update: Add clarification for my 'optional' comment.

    --MidLifeXis

      Thank you! :-)
Re: seek and replace for exceptional characters
by marinersk (Priest) on Sep 23, 2013 at 17:35 UTC
    Everything on the left side of your substitution needs to be a regular expression; special characters need to be escaped, etc.

    As toolic points out, quotemeta will ensure all the rules are followed.

    An example using quotemeta to ensure grep works properly:

    foreach my $searchString (@requestedSearches) { my $searchRegex = quotemeta $searchString; my @matchesFound = grep /$searchRegex/, @dataStore; ... # Do something with @matchesFound }

    And, before you ask, no, there is no inverse function to quotemeta, but a search on PerlMonks will reveal some theoretical almost-reverse techniques that could come in handy some day. :-)

Re: seek and replace for exceptional characters
by Laurent_R (Canon) on Sep 23, 2013 at 18:00 UTC

    Using the quotemeta function is the simplest solution. But so that you understand the underlying reason, your search regex could also be defined as follows (simply escaping the '+' sign):

    my $A = qr (\+#);
      Hi, I just tried quotemeta with my new $A code which is '#i1*#lper/2+#ginsl-#cdz/2'. But it does not work with and without quotementa. I know its a mix of everything but somehow I would like to replace it without interpretation. So my code would be now:
      #!/usr/bin/perl -w #use strict; my $SCU = 'C:/Users/user/Desktop/a.txt'; open (FILE, '<', $SCU) or die "$SCU File not found : $!"; my @lines = <FILE>; close (FILE); my $A= quotemeta '#i1*#lper/2+#ginsl-#cdz/2'; my $B= '$coin22'; my @newlines; push @newlines, s/$A/$B/rg for @lines; open (FILE, '>', $SCU) or die "Could not open file $SCU: $!"; print FILE @newlines; close (FILE);
      Somebody has a suggestion for me? Thanks a lot! Best regards
        Suggestion #1: Uncomment the use strict; line. Set it to autodestruct your computer if you ever accidentally comment it out again.

        Suggestion #2: Withdrawn. I just upgraded to v5.16.3 and your script runs just fine.

        Suggestion #3: Supply test data as previously noted. :-)

        Somebody has a suggestion for me?
        Yes. Show a line of your input file which should match this regular expression.