[英]Perl regular expression variables and matched pattern substitution
當正則表達式保存在變量中時,有人可以解釋正則表達式文本替換嗎? 我正在嘗試處理一些文本(實際上是Clearcase配置規范),並在替換文本時使用。 替換規則保存在具有正則表達式要匹配且文本要替換的哈希數組中。
輸入文本看起來像這樣:
element /my_elem/releases/... VERSION_STRING.020 -nocheckout
大多數替換只是刪除包含特定文本字符串的行,這很好用。 在某些情況下,我想替換文本,但重新使用VERSION_STRING文本。 我試過在替換表達式中使用$ 1,但是它不起作用。 $ 1在比賽中獲取版本字符串,但是替換$ 1在替換中不起作用。
在這些情況下,輸出應如下所示:
element -directory /my_elem/releases/... VERSION_STRING.020 -nocheckout
element /my_elem/releases/.../*.[ch] VERSION_STRING.020 -nocheckout
即。 一行輸入變成了兩個輸出,並且版本字符串已被重新使用。
該代碼看起來像這樣。 首先是正則表達式和替換:
my @Special_Regex = (
{ regex => "\\s*element\\s*\/my_elem_removed\\s*\/main\/\\d+\$", subs => "# Line removed" },
{ regex => "\\s*element\\s*\/my_elem_changed\/releases\/\.\.\.\\s*\(\.\*\$\)",
subs => "element \-directory \/my_elem\/releases\/\.\.\. \\1\nelement \/my_elem\/releases\/\.\.\.\/\*\.\[ch\] \\1" }
);
在第二個正則表達式中,變量$ 1在(。* \\ $)部分中定義,並且工作正常。 subs表達式不能替代它。
foreach my $line (<INFILE>)
{
chomp($line);
my $test = $line;
foreach my $hash (@Special_Regex)
{
my $regex = qr/$hash->{regex}/is;
if($test =~ s/$regex/$hash->{subs}/)
{
print "$test\n";
print "$line\n";
print "$1\n";
}
}
}
我想念什么? 提前致謝。
沒有用於替換表達式的編譯。 因此,您唯一可以做的就是exec或使用e
標志對其進行評估:
if($test =~ s/$regex/eval qq["$hash->{subs}"]/e ) { #...
在替換字符串中將\\\\1
更改為\\$1
后為我工作。
s/$regex/$hash->{subs}/
僅將匹配的部分替換為$hash->{subs}
存儲的文字值作為完整替換。 為了使替換生效,您必須強制Perl將字符串評估為string ,因此這意味着您甚至必須重新添加dquotes才能獲得所需的插值行為(因為它們不是一部分)的字符串。)
但這有點笨拙,因此我將replace表達式更改為subs:
my @Special_Regex
= (
{ regex => qr{\s*element\s+/my_elem_removed\s*/main/\d+$}
, subs => sub { '#Line removed' }
}
, { regex => qr{\s*element\s+/my_elem_changed/releases/\.\.\.\s*(.*$)}
, subs => sub {
return "element -directory /my_elem/releases/... $1\n"
. "element /my_elem/releases/.../*.[ch] $1"
;
}
}
);
我擺脫了一堆您不必在替換表達式中轉義的東西。 由於您要執行的操作是將$1
的值插值到替換字符串中,因此子例程可以簡單地做到這一點。 而且由於$1
在匹配其他內容之前是可見的,因此在運行此代碼時它將是正確的值。
所以現在替換看起來像:
s/$regex/$hash->{subs}->()/e
當然,使它通過 $1
會使它更加防彈,因為您不必依賴全局$1
:
s/$regex/$hash->{subs}->( $1 )/e
當然,您可以這樣更改子代碼:
subs => sub {
my $c1 = shift;
return "element -directory /my_elem/releases/... $c1\n"
. "element /my_elem/releases/.../*.[ch] $c1"
;
}
最后一個注釋: "\\.\\.\\."
沒有按照您的想法做。 您剛在正則表達式中以'...'
結尾,該匹配任何三個字符。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.