正则表达式匹配多个分隔的字符

时间:2009-05-24 08:03:28

标签: regex

在此字符串中:

“< 0><<>><>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

我想匹配“< \ d {1,2}>”的所有实例除了我用一组额外的三角括号进行转义的那些,例如,我想匹配0,2,3,4而不是1,例如:

< 0> << 1>> < 2> > < 3> &LT 4是氢;

我想在一个正则表达式中执行此操作,但我能得到的最好的是:

(^ | [^ \<])\<>([^>] | $)(小于1为卤素\ d {1,2}?)

哪个匹配0,3,4而不是2,例如:

< 0> << 1>>< 2>> < 3> < 4>

是否有人知道如何使用单个正则表达式完成此操作?

6 个答案:

答案 0 :(得分:5)

您还可以尝试conditionals(?(?<=<)(<\d{1,2}>(?!>))|(<\d{1,2}>))

答案 1 :(得分:2)

您可以查看negative look-behind zero-width assertion

(?<!<)<\d{1,2}>

答案 2 :(得分:1)

假设使用输入集

 "<0> <<1>> <2>> <3> <4><<5>"

我们希望匹配0,2,3,4和5.

问题是您需要使用零宽度前瞻零宽度后视,但有三种情况需要匹配,'&lt;','&gt;'和'',和一个不匹配'&lt;&gt;'。此外,如果您希望能够提取已标记的表达式以便将匹配分配给数组,则需要避免标记您不需要的内容。所以我最终得到了非优雅的

use Data::Dumper;

my $a = "<0> <<1>> <2>> <3> <4><<5>";

my $brace_pair = qr/<[^<>]+>/;
my @matches = $a =~ /(?:(?<!<)$brace_pair(?!>))|(?:$brace_pair(?!>))|(?:(?<!<)$brace_pair)/g;

print Dumper(\@a);

如果你想把它塞进一个表达式 - 你可以。

答案 3 :(得分:0)

这是单个正则表达式的替代方案。将其拆分为><边界的列表,然后排除<...>

#!/usr/bin/perl -lw

$s = "<0> <<1>> <2>> <3> <4>";

print join " ",
      map { /(\d+)/; $1 }
      grep !/^<.*>$/,
      split />\s*</, $s;

答案 4 :(得分:0)

如果您正在使用支持外观而非条件的正则表达式(如Java),这是另一种方法:

(?=(<\d{1,2}>))(?!(?<=<)\1(?=>))\1

第一个先行可确保您处于标记的开头并将其捕获以供日后使用。第二个前瞻中的子表达式再次与标记匹配,但前提是它前面有<后跟>。使其成为否定前瞻,实现了您正在寻找的NOT(x和y)语义。最后,第二个\1再次与标签匹配,这次是真实的(即,不在环视中)。

顺便说一句,我可以在第二个前瞻中使用>而不是(?=>),但我认为这种方式更容易阅读并更好地表达我的意图。

答案 5 :(得分:0)

使用Perl以下是一种快速简便的方法。

use strict;
use warnings;

my $str = "<0> <<1>> <2>> <3> <4>";
my @array = grep {defined $_} $str =~ /<<\d+>>|<(\d+)>/g;

print join( ', ', @array ), "\n";