多个匹配的Perl / Regex String Manipulation

时间:2016-03-31 16:36:25

标签: regex perl

我有以下字符串:

List<T>

我需要删除此字符串中的所有内容:

<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“”:

Feed="EUREX-EMDI"
State="CLOSED"
IsTainted="0"

现在看起来像:

s/^[^Feed]*(?=Feed)//;

但是我现在不知道如何在字符串中查找下一部分“State =”CLOSED“”而忽略我已经找到的“Feed =”EUREX-EMDI“”匹配

3 个答案:

答案 0 :(得分:1)

此类事物的perl习语是来自正则表达式捕获组的多重赋值。假设您可以始终依靠相同的顺序和格式(引用)感兴趣的项目:

($feed, $state, $istainted) = /.*(Feed="[^"]*").*(State="[^"]*").*(IsTainted="[^"]*")/;

或者,如果您只想自己捕获(未引用的)值,请更改括号(捕获组):

($feed, $state, $istainted) = /.*Feed="([^"]*)".*State="([^"]*)".*(IsTainted="([^"]*)"/;

答案 1 :(得分:1)

请不要尝试使用正则表达式解析XML。它很脆弱。 XML是上下文的,而正则表达式则不是。所以充其量,这是一个肮脏的黑客,并且可能有一天会因为最无聊的原因而没有警告地休息。

有关详情,请参阅:RegEx match open tags except XHTML self-contained tags

然而,XML 结构化的,实际上很容易使用 - 前提是你使用了适合这项工作的东西:解析器。

我喜欢XML::TwigXML::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";
}

答案 2 :(得分:0)

除了这些字符串之外,这将删除所有字符串

$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)
   |  $ 
 )