【问题标题】:perl regex character classesperl 正则表达式字符类
【发布时间】:2016-06-14 20:55:59
【问题描述】:

我在 perl 中的正则表达式分组遇到问题。

当然,这是一个更大的问题,但它与我正在处理的概念相同。提前感谢大家的 cmets 和想法。

下面的正则表达式应该只关心字符串的这一部分来做出决定。

doctor_who:ee

doctor_who:ep

doctor_who:ex

但不是

doctor_who:eeh

代码:

$str = "doctor_who:ee123ABC451234.123"; #match
$str = "doctor_who:ep123YXZ451234.123"; #match
$str = "doctor_who:ex123451234.123"; #match
$str = "doctor_who:eeh1234LMNOP51234.123";  ##should not match
$str = "doctor_who:abc12341234.123";  ##should not match

$regex = "doctor_who:e[e|p|x]"; #--->problem, what to add/remove?

if ($str =~ m/$regex/){
   print "match!";
}
else {
   print "not matched\n";
}

【问题讨论】:

  • 注意:[e|p|x][epx|] 是一回事;它匹配这四个字符中的任何一个。你的意思是使用[epx]

标签: regex perl


【解决方案1】:

负前瞻零宽度断言很简单。这假设您唯一不想特别匹配的是doctor_who:eeh*

/doctor_who:e(?!eh)[epx]/ 

在上面的例子中,只要我们匹配doctor_who:e,我们就会在每次匹配时触发前瞻。我们可以通过仅在绝对必要时使用它来提高效率,正如@ikegami 在 cmets 中指出的那样:

/doctor_who:e(?:[px]|e(?!h))/ 

除非: 之后的第二个字符不是px,否则只有当该字符是e 时,才会执行此操作。

cmets 中显示的第二个示例根本不使用环视:

/doctor_who:e(?:[px]|e[^h])/

【讨论】:

  • Lookarounds 相当昂贵,所以我会写成/doctor_who:e(?:[px]|e(?!h))/ 甚至/doctor_who:e(?:[px]|e(?:[^h]|\z))/。在实践中,可以使用[^h] 而不是(?:[^h]|\z)
【解决方案2】:

由于您在字符串末尾不匹配,我认为您需要两个正则表达式。

$regex = "doctor_who:e[epx]"; # match
$not_regex "doctor_who:e[epx][a-z]"; #-do not match

那就做吧

if( $string =~ $regex and $string !~ $not_regex ){}

【讨论】:

  • 他没有尝试匹配字符串的末尾。那永远不会匹配
【解决方案3】:

您可以通过两种方式做到这一点,然后将两者结合起来。

使用字符类:

$regex = 'doctor_who:e[epx]';

使用交替:

$regex = 'doctor_who:e(e|p|x)';

这些提供肯定匹配,但它们需要其他东西来拒绝 eeh 匹配。

但是,eeh唯一 匹配拒绝吗?这是你提到的唯一一个,但是,你更喜欢更一般的东西,比如任何 a-z 字符吗? (例如)eec 呢?它应该匹配还是被拒绝?

从示例中,ee1 匹配。这是因为1 不是 h 还是因为它是一个数字?

[至少对我来说]最好、最简洁的正则表达式应该是什么并不完全清楚,因为示例中存在一些漏洞。所以,这里有一些基于我对你真正喜欢的假设所做的正则表达式。

所以,如果 eeh 是唯一的拒绝,请添加:

$regex .= '[^h]';

如果您想要更广泛的拒绝:

$regex .= '[^a-z]';

或者,也许,您只想匹配数字:

$regex .= '[0-9]';

旁注:此答案已被编辑以反映下面的 cmets

【讨论】:

  • OP 没有尝试匹配字符串的末尾。如果要这样做,则必须以特定长度 substr 字符串(或仅提取所需的部分),然后与 $ 匹配
  • 那也行不通。单词边界是空格,在他试图击中的内容之后没有空格:)
  • 看我之前的评论
  • @stevieb 我一直在努力。从顶部看,如果前两个字符匹配,则拒绝似乎是 [仅] eeh。但是,eec 也应该失败[但ee1 匹配]?在这一点上,对我来说,即使给出了示例,意图/标准也不清楚
  • $regex .= '[^h]'; 不允许 :eph:exh:eeh 匹配
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-19
相关资源
最近更新 更多