2011-04-21 65 views
3
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,但它不起作用。我該怎麼辦?非常感謝。

+0

我沒有時間現在嘗試它,但嘗試使用正則表達式引用而不是未插入的字符串。 ''pwd(\\ s *)=。*'=> qr/pwd $ 1 = $ newPasswd /,'。此外,如果你需要在元組的第一部分使用反向引用,可以考慮只使用一個數組並且一次剝離兩個元素,或者如果這給了willies,可以使用如下的數組引用:'my @pwMap =([ 'foo','bar'],['baz','buz']);這些方法比hash更好,因爲任何標量值都可以存儲在每個有序對的第一個元素中。 – daotoad 2011-04-21 17:13:46

+0

[在Perl正則表達式替換中使用$ 1與\ 1有什麼區別?](http://stackoverflow.com/questions/3068236/what-is-the-difference-between-using-1-vs- 1-per-per-regex-substitutions) – 2017-02-03 09:04:46

回答

6

\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', 
0

假設你的模式匹配的地圖格局保持不變,爲什麼不能擺脫它,簡單地說:

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

看起來他正試圖保留空白。你可能需要'\ K'在'\ s *'之後 - 或者你打算在'=' – Axeman 2011-04-21 20:37:24

1

我看到你的代碼有很多重複的。

假設您使用的是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; 
+0

Brad開始比賽,你的代碼很乾淨漂亮!謝謝! – John 2013-10-18 16:04:35