0
my $st = 'abcd';
my $grep1 = 'a(bc)d';
my $grep2 = '$1';
$st =~ s/$grep1/$grep2/;
print $st,"\n";

If you run the code, the output is '$1', but I want to see 'bc'.

$grep2 can not be put directly into a regular expression, because the input value.

How can I do it?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 2
    You can also do it [this way](https://ideone.com/zI4MKa). – Wiktor Stribiżew Nov 24 '15 at 07:33
  • See also [How to use a variable in the replacement side of the Perl substitution operator?](http://stackoverflow.com/questions/392643/how-to-use-a-variable-in-the-replacement-side-of-the-perl-substitution-operator) and [Using the ee modifier safely with the s/// operator when the right side is input from user](http://stackoverflow.com/questions/29107353/using-the-ee-modifier-safely-with-the-s-operator-when-the-right-side-is-input) – Håkon Hægland Nov 24 '15 at 10:10

2 Answers2

4

The following will do what you want:

use String::Substitution qw( sub_modify );

my $st = 'abcd';
my $grep1 = 'a(bc)d';
my $grep2 = '$1';
sub_modify($st, $grep1, $grep2);
print $st,"\n";

The advantage of this solution is that it doesn't allow the execution of arbitrary code such as eval EXPR (aka /ee) does.

ikegami
  • 367,544
  • 15
  • 269
  • 518
2

One solution in this specific context is to use the /e modifier twice

#!/usr/bin/env perl

use strict;
use warnings;

my $st = 'abcd';
my $grep1 = 'a(bc)d';
my $grep2 = '$1';

$st =~ s/$grep1/$grep2/ee;

print $st,"\n";

Outputs:

bc

To make it a little less fragile, I'd recommend enclosing your RHS in two sets of quotes though:

$st =~ s/$grep1/qq{qq{$grep2}}/ee;

Note: As ikegami mentioned, evaling unsantized input is extremely dangerous. I would therefore not recommend this in a general context. Also, there are likely better solutions available to you, but you would first have to unravel your XY nature of question.

Community
  • 1
  • 1
Miller
  • 34,962
  • 4
  • 39
  • 60
  • Thanks body~ it's simple and great answer! – user3934476 Nov 24 '15 at 06:27
  • This is an awful answer. This solution is insanely dangerous, and you didn't even mention it! – ikegami Nov 24 '15 at 06:38
  • It also fails for `my $grep2 = '[$1]';`, which I'm sure the OP expects to produce `[bc]`. – ikegami Nov 24 '15 at 06:57
  • 2
    @ikegami Yes it's dangerous, warning added. And yes, I know the solution is fragile and would fail with different input, which is why I had already offered the second less fragile option. Regardless, I'll gladly vote your cpan module suggestion. – Miller Nov 24 '15 at 08:17
  • What are you talking about? Your second solution is no better. It might handle `my $grep2 = '[$1]';`, but it fails for `my $grep2 = '}$1{';`. More importantly, it's equally as dangerous, allowing arbitrary code to be executed. – ikegami Nov 24 '15 at 15:26
  • @ikegami Yes, I already stated that it was potentially fragile, although your counter example is obviously contrived. And yes it is potentially dangerous, but you are assuming that his use case is data from external sources. We do not know that. Regardless, your solution is definitely better even though it requires a cpan install which is why I upvoted it. I don't think we actually have a disagreement here. – Miller Nov 24 '15 at 18:12
  • Using `}` in a replacement expression isn't contrived by a long shot!!!!! /// Re "you are assuming that his use case is data from external sources". Nope. not at all. I didn't say "it's vulnerable to attack", I said "it's fragile", meaning it doesn't work for even legitimate inputs. /// Re "I don't think we actually have a disagreement here", your edit helps, but 1) you're still advocating a very bad solution, and 2) it doesn't just fail for unsanitiized inputs as you say. – ikegami Nov 24 '15 at 18:22
  • @ikegami Yes, one should be the effect unbalanced braces within a qq{}, but for 99% of the data that I typically see this isn't an issue and that is why I call your counter example a bit contrived. If you disagree, that's fine. And I'm not advocating my solution, I'm only offering. If I had known of the CPAN module that you suggested, I would have proposed it. That's one reason why i upped your answer after you posted it. But otherwise, I'm content to let SO work the way it's supposed to and let yours rise based off of user voting. The system is working. – Miller Nov 24 '15 at 20:06
  • @ikegami I offered "a" solution to his question in this "specific context". Meaning the exact data posed in the question. I make/made no claims that it is/was "the" solution, as this is likely an XY problem either way. And I've also qualified the answer plenty, as have you. And to answer your why? To educate. – Miller Nov 24 '15 at 20:41
  • I stand by what I said then. You are advocating a very bad solution. We both know `$grep2` isn't static (or you would have suggested `s/$grep1/$1/`). I don't see why you think this is XY. /// To educate??!?! Damn straight it does. That's why I have a problem with your post. You are education people into doing the wrong thing. – ikegami Nov 24 '15 at 20:57