Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

replacing equal to operator

by ty_sopw (Novice)
on Jan 28, 2021 at 18:32 UTC ( #11127585=perlquestion: print w/replies, xml ) Need Help??

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

I have an input string in the format key=value and the value always ends with a line break i.e. \n. I need to double quote the value part of my string, excluding the line break and I did the following to do that, but, for some reason, the equal to operator isn't registering in my substitue operation; my output remains the same as input even after the substitute operation. How can I achieve this?

#input string: parameter=TO_DATE('1900-01-01','YYYY-MM-DD')\n #desired output: parameter="TO_DATE('1900-01-01','YYYY-MM-DD')"\n $input_string =~ s/"="/"=\""/esg; $input_string =~ s/"\n"/"\"\n"/esg; print "$input_string";

Replies are listed 'Best First'.
Re: replacing equal to operator
by haukex (Bishop) on Jan 28, 2021 at 18:46 UTC

    You don't need all those double quotes in the regexes. On the left-hand side, they're being taken literally, so just remove them, and on the right-hand side, you need them because of the /e modifier, but since you're not actually making use of that, get rid of the /e modifier and the double quotes on the right-hand side. In other words, s/=/="/ and s/\n/"\n/ (or s/$/"/ for the latter). No need for the /gs modifiers either.

    However, the solution as you've currently written it seems brittle to me: In particular, it'll replace any equals sign. Personally, I'd either see if there is an existing module to parse whatever file format this is, and if there isn't, I'd try to parse the values myself, maybe something like the following. Note how you can extend the regex to do more, like for example I've designed it so that it won't add double quotes if there are already double quotes around the string, and reject the input if those double-quotes are unbalanced.

    use warnings; use strict; use Test::More; my $string=qq{parameter=TO_DATE('1900-01-01','YYYY-MM-DD')\n}; my $REGEX = qr{^ (\w+) = (?| "(.+)" | ( (?!").+(?<!") ) ) (\n|\z) }x; if ( $string =~ $REGEX ) { $string = qq{$1="$2"$3} } else { die "failed to parse $string" } is $string, qq{parameter="TO_DATE('1900-01-01','YYYY-MM-DD')"\n}; done_testing;

      getting rid of all the escaping, extra quotes and the e and s options worked. thank you

Re: replacing equal to operator
by LanX (Cardinal) on Jan 28, 2021 at 18:43 UTC
    Here a minimal demo in the debugger to highlight your problems.

    DB<8> $_= "parameter=TO_DATE('1900-01-01','YYYY-MM-DD')\n" DB<9> s/=/="/ DB<10> s/\n/"\n/ DB<11> p $_ parameter="TO_DATE('1900-01-01','YYYY-MM-DD')" DB<12>

    But I'd rather suggest using split /=/ and join on individual lines, using your regexes on a complete file will cause havoc if the RHS contains any '='.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

Re: replacing equal to operator
by Fletch (Chancellor) on Jan 28, 2021 at 18:44 UTC

    You're overcomplicating things perhaps . . .

    $ perl -E '$_=qq{parameter=TO_DATE('1900-01-01','YYYY-MM-DD')\n};print + qq{Before: $_};s{=(.*)$}{="$1"};print qq{ After: $_}' Before: parameter=TO_DATE(1900-01-01,YYYY-MM-DD) After: parameter="TO_DATE(1900-01-01,YYYY-MM-DD)"

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      I came up with the same approach but you don't even need that $ because the dot doesn't match the newline by default.

      use strict; use warnings; use Test::More tests => 1; my $have = qq#parameter=TO_DATE('1900-01-01','YYYY-MM-DD')\n#; my $want = qq#parameter="TO_DATE('1900-01-01','YYYY-MM-DD')"\n#; $have =~ s/=(.*)/="$1"/; is $have, $want;


Re: replacing equal to operator
by jdporter (Canon) on Jan 28, 2021 at 19:05 UTC

    I'm sorry -- why doesn't this work?:


      It works, but using a backreference \1 in place of a capture variable $1 in the replacement string is Frowned Upon and will earn you a warning:

      Win8 Strawberry (32) Thu 01/28/2021 14:55:21 C:\@Work\Perl\monks >perl -Mstrict -Mwarnings use Data::Dump qw(dd); my $s = "parameter=TO_DATE('1900-01-01','YYYY-MM-DD')\n"; dd 'before:', $s; $s =~ s/=(.*)/="\1"/; \1 better written as $1 at - line 7. dd 'after:', $s; ^Z ("before:", "parameter=TO_DATE('1900-01-01','YYYY-MM-DD')\n") ( "after:", "parameter=\"TO_DATE('1900-01-01','YYYY-MM-DD')\"\n", )

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

      You need "=" in substitution field. Replace "\1" with "$1" per warnings.
      use strict; use warnings; use Test::Simple tests=>1; my $input_string = qq(parameter=TO_DATE('1900-01-01','YYYY-MM-DD')\n); my $desired_output = qq(parameter="TO_DATE('1900-01-01','YYYY-MM-DD')" +\n); my $output = $input_string =~ s/=(.*)/="$1"/r; ok( $output eq $desired_output, $output );


      1..1 ok 1 - parameter="TO_DATE('1900-01-01','YYYY-MM-DD')" #
        You need "=" in substitution field.

        And I had it. What's your point?

A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11127585]
Approved by LanX
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (4)
As of 2021-05-05 20:46 GMT
Find Nodes?
    Voting Booth?
    Perl 7 will be out ...

    Results (69 votes). Check out past polls.