【问题标题】:perl regex warning: \1 better written as $1 at (eval 1) line 1perl 正则表达式警告:\1 最好在 (eval 1) 第 1 行写成 $1
【发布时间】:2011-04-21 17:10:14
【问题描述】:
use strict;
use warnings;

my $newPasswd = 'abc123';
my @lines = ( "pwd = abc", "pwd=abc", "password=def", "name= Mike" );

my %passwordMap = (
    'pwd(\\s*)=.*'      => 'pwd\\1= $newPasswd',
    'password(\\s*)=.*' => 'password\\1= $newPasswd',
);

print "@lines\n";

foreach my $line (@lines) {
    while ( my ( $key, $value ) = each(%passwordMap) ) {
        if ( $line =~ /$key/ ) {
            my $cmdStr = "\$line =~ s/$key/$value/";
            print "$cmdStr\n";
            eval($cmdStr);
            last;
        }
    }
}

print "@lines";

运行它会给我正确的结果:

pwd = abc pwd=abc password=def name= Mike
$line =~ s/pwd(\s*)=.*/pwd\1= $newPasswd/
\1 better written as $1 at (eval 2) line 1 (#1)
$line =~ s/password(\s*)=.*/password\1= $newPasswd/
\1 better written as $1 at (eval 3) line 1 (#1)
pwd = abc123 pwd=abc password= abc123 name= Mike

我不想看到警告,尝试使用 $1 而不是 \1,但它不起作用。我应该怎么办?非常感谢。

【问题讨论】:

  • 我现在没有时间尝试,但尝试使用正则表达式引用而不是未插值的字符串。 'pwd(\\s*)=.*' => qr/pwd$1= $newPasswd/,。此外,如果您在元组的第一部分需要反向引用,请考虑只使用一个数组并一次剥离两个项目,或者如果这给了您威力,请使用数组引用数组,如下所示:`my @pwMap = ([ 'foo','bar'], ['baz', 'buz']);这些方法比散列更好,因为任何标量值都可以存储在每个有序对的第一个元素中。

标签: perl syntax warnings


【解决方案1】:

\1 是一个正则表达式模式,意思是“匹配第一组捕获括号捕获的内容”。在替换表达式中使用它绝对没有意义。要获取第一组捕获括号捕获的字符串,请使用$1

$line =~ s/pwd(\s*)=.*/pwd\1= $newPasswd/

应该是

$line =~ s/pwd(\s*)=.*/pwd$1= $newPasswd/

所以

'pwd(\\s*)=.*'      => 'pwd\\1= $newPasswd',
'password(\\s*)=.*' => 'password\\1= $newPasswd',

应该是

'pwd(\\s*)=.*'      => 'pwd$1= $newPasswd',
'password(\\s*)=.*' => 'password$1= $newPasswd',

或者更好

qr/((?:pwd|password)\s*=).*/ => '$1= $newPasswd',

【讨论】:

    【解决方案2】:

    我看到你的代码中有很多重复。

    假设您使用的是 Perl 5.10 或更高版本,这就是我编写代码的方式。

    use strict;
    use warnings;
    use 5.010;
    
    my $new_pass = 'abc123';
    my @lines = ( "pwd = abc", "pwd=abc", "password=def", "name= Mike" );
    
    my @match = qw'pwd password';
    my $match = '(?:'.join( '|', @match ).')';
    
    say for @lines;
    say '';
    
    s/$match \s* = \K .* /$new_pass/x for @lines;
    # which is essentially the same as:
    # s/($match \s* =) .* /$1$new_pass/x for @lines;
    
    say for @lines;
    

    【讨论】:

      【解决方案3】:

      假设你的模式匹配图的模式保持不变,为什么不去掉它,简单地说:

      $line =~ s/\s*=.*/=$newPassword/
      

      【讨论】:

      • 看起来他正在尝试保留空白。您可能需要在\s* 之后添加\K--或者您可能打算在= 开始比赛
      猜你喜欢
      • 1970-01-01
      • 2016-01-03
      • 1970-01-01
      • 2010-11-07
      • 2012-12-16
      • 1970-01-01
      • 2014-01-15
      • 2011-05-09
      • 1970-01-01
      相关资源
      最近更新 更多