[英]Replace strings only within a regex match in perl
我有一個XML文檔,其屬性值中包含文本。 我無法更改XML文件的生成方式,但是需要提取屬性值而不丟失\\ r \\ n。 XML解析器當然會將它們剝離。
所以我試圖用實體引用替換屬性值中的\\ r \\ n,因為它是非貪婪的匹配,所以我使用perl來做到這一點。 但是我需要幫助才能讓替換只在比賽中進行。 或者我需要一個更簡單的方法來做到這一點:)
這是我到目前為止的內容:
perl -i -pe 'BEGIN{undef $/;} s/m_description="(.*?)"/m_description="$1"/smg' tmp.xml
這與我需要使用的內容相匹配:(。*?)。 但是我不知道擴展該模式以匹配其中的\\ r \\ n並在結果中進行替換。 如果我知道我可以有多少個\\ r \\ n,但是似乎我需要可變數量的捕獲組或類似的東西? 正則表達式有很多我不了解的地方,似乎應該做些什么。
例:
preceding lines
stuff m_description="Over
any number
of lines" other stuff
more lines
應該去:
preceding lines
stuff m_description="Over any number of lines" other stuff
more lines
解
感謝Ikegam和ysth提供的解決方案,對於5.14+,它是:
perl -i -0777 -pe's/m_description="\K(.*?)(?=")/ $1 =~ s!\n! !gr =~ s!\r! !gr /sge' tmp.xml
.
應該已經匹配\\n
(因為您指定了/s
標志)和\\r
。
要替換結果,請使用/e
:
perl -i -0777 -pe's/(?<=m_description=")(.*?)(?=")/ my $replacement=$1; $replacement=~s!\n! !g; $replacement=~s!\r! !g; $replacement /sge' tmp.xml
我還更改了它以使用lookbehind / lookahead簡化代碼,並使用-0777將$/
設置$/
slurp模式並刪除無用的/m
。
好的,雖然這看起來像是XML問題,但事實並非如此。 XML問題是生成它的人。 您可能應該給他們一個帶有規格匯總的產品,作為“修復”此問題的第一個呼吁。
否則,我將采用兩次通過方法,即閱讀文本,找到與描述匹配的所有“斑點”,然后全部替換。
像這樣:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my $text = do { local $/ ; <DATA> };
#filter text for 'description' text:
my @matches = $text =~ m{m_description=\"([^\"]+)\"}gms;
print Dumper \@matches;
#Generate a search-and-replace hash
my %replace = map { $_ => s/[\r\n]+/ /gr } @matches;
print Dumper \%replace;
#turn the keys of that hash into a search regex
my $search = join ( "|", keys %replace );
$search = qr/\"($search)\"/ms;
print "Using search regex: $search\n";
#search and replace text block
$text =~ s/m_description=$search/m_description="$replace{$1}"/mgs;
print "New text:\n";
print $text;
__DATA__
preceding lines
stuff m_description="Over
any number
of lines" other stuff
more lines
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.