[英]Perl / Regex String Manipulation for multiple matches
我有以下字符串:
<Multicast ID="0/m1" Feed="EUREX-EMDI" IPPort="224.0.50.128:59098" State="CHECK" IsTainted="0" UncrossAfterGap="0" ManualUncrosses="0" AutoUncrosses="0" ExpectedSeqNo="-" />
我需要除去以下內容:
Feed="EUREX-EMDI"
State="CLOSED"
IsTainted="0"
我設法通過以下代碼獲取“ Feed =“ EUREX-EMDI””:
s/^[^Feed]*(?=Feed)//;
所以現在看起來像:
Feed="EUREX-EMDI" IPPort="224.0.50.0:59098" State="CLOSED" IsTainted="0" UncrossAfterGap="0" ManualUncrosses="0" AutoUncrosses="0" ExpectedSeqNo="2191840" />
但是我現在不知道如何在字符串中查找下一部分“ State =“ CLOSED”“,而忽略我已經找到的” Feed =“ EUREX-EMDI”“匹配項
這種事情的perl習慣用法是來自正則表達式捕獲組的多重分配。 假設您始終可以指望感興趣的項目以相同的順序和格式(引用):
($feed, $state, $istainted) = /.*(Feed="[^"]*").*(State="[^"]*").*(IsTainted="[^"]*")/;
或者,如果您只想自己捕獲(未加引號的)值,請更改括號(捕獲組):
($feed, $state, $istainted) = /.*Feed="([^"]*)".*State="([^"]*)".*(IsTainted="([^"]*)"/;
請不要嘗試使用正則表達式解析XML。 很脆 XML是上下文的,而正則表達式則不是。 因此,充其量,這是一個骯臟的駭客,並且可能出於最荒唐的原因而有一天可能在沒有警告的情況下中斷。
請參閱: RegEx匹配除XHTML自包含標記之外的其他開放標記 。
但是,XML 是結構化的,並且實際上很容易使用-只要您使用非常適合該工作的內容:解析器即可。
我喜歡XML::Twig
。 XML::LibXML
也很出色,但是學習曲線有些陡峭。 (您還可以獲得類似於正則表達式的XPath
,但更適合XML)
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
#create a list of what we want to keep. This map just turns it
#into a hash.
my %keep = map { $_ => 1 } qw ( IsTainted State Feed );
#parse the XML. If it's a file, you may want "parsefile" instead.
my $twig = XML::Twig->parse( \*DATA );
#iterate the attributes.
foreach my $att ( keys %{ $twig->root->atts } ) {
#delete the attribute unless it's in our 'keep' list.
$twig->root->del_att($att) unless $keep{$att};
}
#print it. You may find set_pretty_print useful for formatting XML.
$twig->print;
__DATA__
<Multicast ID="0/m1" Feed="EUREX-EMDI" IPPort="224.0.50.128:59098" State="CHECK" IsTainted="0" UncrossAfterGap="0" ManualUncrosses="0" AutoUncrosses="0" ExpectedSeqNo="-" />
輸出:
<Multicast Feed="EUREX-EMDI" IsTainted="0" State="CHECK"/>
這樣可以保留屬性,並為您提供有效的XML。 但是,如果您只想要這些值:
foreach my $att ( qw ( Feed State IsTainted ) ) {
print $att, "=", $twig->root->att($att),"\n";
}
這將除去所有那些字符串。
$str =~ s/(?s)(?:(?!(?:Feed|State|IsTainted)\\s*=\\s*".*?").)*(?:((?:Feed|State|IsTainted)\\s*=\\s*".*?")|$)/$1/g;
如果要包括空格分隔符,請替換為' $1'
。
講解
(?s) # Dot - all
(?: # To be removed
(?!
(?: Feed | State | IsTainted )
\s* = \s* " .*? "
)
.
)*
(?: # To be saved
( # (1 start)
(?: Feed | State | IsTainted )
\s* = \s* " .*? "
) # (1 end)
| $
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.