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";
Re: replacing equal to operator
by haukex (Archbishop) 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;
| [reply] [d/l] [select] |
|
| [reply] |
Re: replacing equal to operator
by LanX (Saint) 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 '='.
| [reply] [d/l] |
Re: replacing equal to operator
by Fletch (Bishop) on Jan 28, 2021 at 18:44 UTC
|
$ 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.
| [reply] [d/l] |
|
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;
| [reply] [d/l] |
Re: replacing equal to operator
by jdporter (Paladin) on Jan 28, 2021 at 19:05 UTC
|
s/=(.*)/="\1"/;
| [reply] [d/l] |
|
Win8 Strawberry 5.8.9.5 (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: <%-{-{-{-<
| [reply] [d/l] [select] |
|
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 );
OUTPUT:
1..1
ok 1 - parameter="TO_DATE('1900-01-01','YYYY-MM-DD')"
#
| [reply] [d/l] [select] |
|
| [reply] |
|
A reply falls below the community's threshold of quality. You may see it by logging in. |
|
|