什么正则expression式提取所有的数据,除了在<>在Perl中?

我有string

Message <Network=Data Center> All Verified 

我需要提取除括号之外的所有string

我试过了

 m/(?![^<]*\\>)/s 

没有给出预期的结果。

删除<..>区域

从字符串中删除<..>部分,然后处理剩下的字符串更容易。

试试这个oneliner:

 cat file | perl -pne 's/<[^>]*?>//g;' 

对于您的示例输入,这是输出:

 Message All Verified 

注意非贪婪的量词 ? 在正则表达式中使用。 另外,因为这是一个oneliner,所以s/// search-and-replace结构被应用于$_隐式变量(这是一个来自标准输入的行)。 所以在搜索和替换运行后, $_将被改变(将不会有<..>区域)。 另外,为了在运行代码块之后打印变量$_ ,还使用了-p 。 您可以在perlrun中阅读关于Perl命令行开关的更多信息。

这是一个解决方案。 下面还有一个:

捕获<..>之外的区域

另一方面,你可以(如果你想)匹配<..>区域以外的部分。

为了做到这一点,让我们建立一个正则表达式。 首先,我们要一个<>自由区域。 下面的正则表达式匹配

$p = ([^<>]*)

接下来,我们希望在<之前匹配所有内容,为此我们可以编写(?:$p<)>之后的所有内容,即(?:>$p)

现在,如果我们将所有这些部分组合在一起,我们得到(?:>$p)|(?:$p<)

注意(?:)是一个非捕获组。

所以现在有两个捕获组(两个$p你看到上面),但只有一个将匹配一次,所以一些捕获将是undef 。 我们将不得不将这些过滤掉。

最后,我们可以组装所有的捕获,我们就完成了。

 cat file | perl -ne '$p="([^<>]*)";@x=grep{defined} m{(?:>$p)|(?:$p<)}g; print join(" ",@x)."\n";' 

Parse::Yapp解析器

你可能会认为使用Parser::Yapp这个特定的问题有点太多了(通常,如果你有一些复杂的解析,你会使用语法和解析器生成器 ),但..为什么不.. .. 🙂

好的,我们需要一个语法,这里是一个grammar_file.yp

 #header %% #rules expression: | exterior '<' interior '>' exterior | exterior ; exterior: | TOK { $_[0]->YYData->{DATA} .= $_[1]; } | expression ; interior: TOK; %% #footer sub Error { my ($parser)=shift; } sub Lexer { use Data::Dumper; my($parser)=shift; $parser->YYData->{INPUT} or return('',undef); #$parser->YYData->{INPUT}=~s/^\s+//; for ($parser->YYData->{INPUT}) { return ('TOK',$1) if(s/^([^<>]+)//); return ( $1,$1) if(s/^([<>])//); }; } 

你会注意到在上面的语法interior完全忽略了interior ,只有exterior的终端被收集。

这是一个小程序,它将使用解析器(从grammar_file.yp生成的grammar_file.ypparse.pl

 #!/usr/bin/env perl use strict; use warnings; use MyParser; my $parser=MyParser->new; $parser->YYData->{INPUT} = "Message <Network=Data Center> All Verified"; my $value=$parser->YYParse( yylex => \&MyParser::Lexer, yyerror => \&MyParser::Error, #yydebug => 0x1F, ); my $nberr=$parser->YYNberr(); my $data=$parser->YYData->{DATA}; print "Result=$data" 

现在一个Makefile ,我们完成了:

 generate_parser_module: yapp -m MyParser grammar_file.yp; run: perl parse.pl all: generate_parser_module 

注意

更多的分析器发生器可以在这里找到

  • 正则表达式语法::
  • 解析:: RecDescent的
  • Marpa :: XS或Marpa :: R2

你可以用其他方法来做:只要在尖括号中删除字符串:

 s@<.*>@@ 

或者如果不允许:

 s@<[^>]*>@@ 

你可以使用sed

 cat yourfile |sed 's/<.*>//g' > newfile 

如果你需要perl

  perl -i -pe "s/<.*?>//g" yourfile 

这是一个紧凑的方法。 下面的正则表达式将把你的字符串捕获到组1中:

 <[^>]+>|([^<>]*) 

我们在这里感兴趣的不是总体比赛,而只是第一组比赛。

所以我们需要遍历组1匹配。 我不用Perl编写代码,但是遵循perlretut教程的配方,应该这样做:

  while ($x =~ /<[^>]+>|([^<>]*)/g) { print "$1","\n"; } 

请尝试一下,让我知道,如果它适合你。