开发者

Uninitialized Backreference in Substitution

开发者_高级运维

Assuming that I must do this substitution using a single substitution, what is the preferred method to avoid this error:

Use of uninitialized value $2 in concatenation (.) or string at -e line 1.

With this Perl code:

perl -e 'use strict;use warnings;my $str="a";$str=~s/(a)|(b)/$1foo$2/gsmo;'

The goal here is to either print "afoo" or "foob" depending on what $str contains.

I can use no warnings; but then I am worried I will miss other "real" warnings. I also know that using one pattern makes this convoluted but my actual pattern is much more complicated.

If you care the actual replacements are closer to:

#!perl
my $search = q~(document\.domain.*?</script>)|(</head>)~;
my $search_re = qr/$search/smo;
my $replace = q("$1
<script src=\"/library.js\"></script>
$2");
while (<*.tmpl>) {
  my $str = fead_file($_);
  $str =~ s/$search_re/$replace/gee;
}

But even more complicated, basically the above code just reads from a DB to get the search & replace and then does them to the template. Having to run this script twice with every commit would introduce too much overhead, apparently... so says them...


You could:

my $replace = q("@{[$1||'']}
<script src=\"/library.js\"></script>
@{[$2||'']}");

(using // instead of || on 5.10+)


Still works with /g:

s/(a)|(b)/ ($1 // '') . 'foo' . ($2 // '') /ge


Well, you can't find both "a" and "b" when you specifically say OR (|). Also, you cannot concatenate the strings by placing the variable name next to the text, e.g. $1foo.

I'm not quite sure what you are saying about overhead, but you do need to check the match in order to do a correct replacement.

s/(a)/$1 . "foo"/ge || s/(b)/"foo" . $1/ge;

This might work. If the first one works, the second won't be executed (short circuit OR).


Similar to ikegami's solution, if you want to hold the replacement in a variable you can call a code reference in s///e passing it the captures.

#!perl
my $search = q~(document\.domain.*?</script>)|(</head>)~;
my $search_re = qr/$search/smo;
my $replace = sub {
    my $one = shift || '';
    my $two = shift || '';
    return qq($one\n<script src="/library.js"></script>\n$two);
}
while (<*.tmpl>) {
  my $str = fead_file($_);
  $str =~ s/$search_re/$replace->($1, $2)/ge;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜