使用正则表达式创建子集

时间:2019-04-02 16:54:48

标签: regex perl

我有以下维度元素列表(不完整,实际上要长得多):

Ktr_12345_180
Ktr_12345_160
Ktr_12345_1130
Kst_12345_180
Kst_12345_112
Kst_12345_120
Kst_12345_160

我的目标是在Jedox 2019.1 Subset-Editor中创建元素的子集。 子集应包含所有以前缀"Ktr_"开头的元素,但不带有后缀_160_180

我已经构建了一个正则表达式(Ktr_)+[0-9]+(_180|_160),用于标识不需要的元素。

现在我必须将其反转。据我所知,没有用于反转正则表达式的本机功能,对吧?

因此,我尝试通过使用否定的超前行为来做到这一点:(Ktr_)+[0-9]+(?!(_180|_160))

这根本不起作用。我尝试了各种形状,但没有达到目标...

我希望正则表达式能够提供所需的元素。相反,它仅显示每个以"Ktr_"作为前缀的元素。

4 个答案:

答案 0 :(得分:4)

问题在于+贪婪的程度只在于它满足整个模式的匹配;在[0-9]+中,它与 all 后面的数字不匹配,但仅与所有匹配,因此其余模式也匹配

捕获模式([0-9]+)的可变部分并打印出来以查看

my @ary = qw(
    Ktr_12345_180
    Ktr_12345_160
    Ktr_12345_1130  
    Kst_12345_180
);

for (@ary) { 
    say "got $1  in $_"  if /(Ktr_[0-9]+)(?!_180|_160)/;
}

我们得到

got Ktr_1234   in Ktr_12345_180
got Ktr_12345   in Ktr_12345_1130
got Ktr_1234   in Ktr_12345_160

匹配1234会使5满足1234之后的先行的“ not _180”要求。

要解决此问题,我们需要数据详细信息,问题似乎允许两种可能性

  • 如果像样本数据所示的那样总是跟随_,则只需在前瞻之前添加_

    /Ktr_[0-9]+_(?!180|160)/
    

    现在要求在_之前匹配所有数字。这也“强制”了_

  • 如果我们按照文字所说

      

    所有以前缀“ Ktr_”开头但不具有后缀_160或_180的元素

    那么Ktr_12345之后可能没有任何东西,或者至少没有_

    在这种情况下,仅强制匹配所有连续的数字

    /Ktr_[0-9]++(?!_180|_160)/
    

    其中多余的+使其前一个子模式尽可能地匹配,而不管整个模式中的后续情况如何;它以possesive quantifiers

  • 为名

答案 1 :(得分:1)

另一种方法是匹配模式,然后对后面的负向求反。

尝试一下

$ cat paul.txt
Ktr_12345_180
Ktr_12345_160
Ktr_12345_1130
Kst_12345_180
Kst_12345_112
Kst_12345_120
Kst_12345_160
$ perl -lne ' print if /(Ktr_).+?(?<!_180|_160)\b/ ' paul.txt
Ktr_12345_1130
$ perl -lne ' print if /(Ktr_)+[0-9]+.+?(?<!_180|_160)\b/ ' paul.txt
Ktr_12345_1130
$

答案 2 :(得分:0)

您需要的正确正则表达式是这个

\bKtr_[0-9]+_(?!1[68]0\b)[0-9]+\b

在正则表达式周围的\b字边界确保它不会在较大的文本中提供部分匹配,并且(?!1[68]0\b)是拒绝160180,其余模式与您的相似。另外,除非您需要一个小组,否则您无需将第一部分写为(Ktr_)+,这也将使Ktr_的整个部分进行一次或多次,而查看样本不会认为您想。因此,我仅将其更改为简单的Ktr_,但如果确实有效且确实需要,请通过将Krt_替换为(Ktr_)+

来保留它。

Demo

答案 3 :(得分:0)

您可以将所有格量词与附加的+配合使用,以确保[0-9]+匹配出现的数字,并且在匹配失败时不尝试回溯。

(Ktr_)+[0-9]++(?!(_180|_160))

Possessive quantifiers从Perl 5.10开始可用,或者在此之前使用independent subexpression语法。