【问题标题】:correct usage of carets inside negative lookahead expression in perl在 perl 中的负前瞻表达式中正确使用插入符号
【发布时间】:2013-09-15 22:22:44
【问题描述】:

我正在尝试匹配任何不完全由大写或小写字母组成的单词,并且我编写了以下正则表达式:

if ($line =~ /(?!^[A-Z][A-Z]+(\s*)$)(?!^[a-z][a-z]+(\s*)$)/) {
    print $line;
}

下面的表达式应该匹配所有大写字母的单词

(?!^[A-Z][A-Z]+(\s*)$) 

这应该匹配所有小写字母的单词

(?!^[a-z][a-z]+(\s*)$)

我将两者结合起来并尝试将其与以下单词匹配:ASDSFSDF、asdfasdfasdf 和 asdasdfFFFdsfs。我注意到它匹配一切。仅当我将插入符号移到括号外时,如下所示:

^(?![A-Z][A-Z]+(\s*)$)^(?![a-z][a-z]+(\s*)$)/)

我是否看到它只加工 asdasdfFFFdsfs。有人可以向我解释为什么我需要将运算符移到负前瞻表达式之外?我是 regexp 的新手,我很困惑。

谢谢。

【问题讨论】:

  • [A-Z][A-Z]+ 部分等同于[A-Z]{2,},这意味着它将匹配至少两个或多个大写字母。也许这就是你想要做的,在这种情况下,后一种正则表达式更具可读性,IMO。

标签: regex perl


【解决方案1】:

你陷入了多重否定和锚定的陷阱,而你得到的正则表达式并没有完全达到你想要的效果。假设我们只有简化的正则表达式 /(?!^[A-Z]$)/ 和字符串 "1"

在第一个位置(1 之前),测试断言。 ^ 在这里匹配,但 [A-Z] 不匹配。因此,^[A-Z]失败。由于前瞻是,因此整个模式成功。

现在假设我们有字符串"A"。在第一个位置,断言被测试。模式^[A-Z]$ 在这里匹配。因为它是负前瞻,所以断言失败。

然后,测试第二个位置(在A 之后)。断言已经过测试,但 ^ 在这里不匹配 - 因此否定断言使模式成功!

因此,您的正则表达式与您想要的模式不匹配。您可以通过在断言之外锚定来抑制这种行为:

/^(?![A-Z]$)/

在这种情况下。请注意,在您的情况下,最简单的解决方案是编写一个匹配您 想要的所有输入的正则表达式,并否定该结果:

print $line unless $line =~ /^(?:[A-Z]{2,}|[a-z]{2,})\s*$/;

(编辑:实际上 TLP 的第二个解决方案更简单,而且可能更有效)

【讨论】:

  • 我很欣赏详细的解释。这让我明白了很多。我认为里面的表达式 ^[a-z][a-z]+(\s*)$ 会匹配以小写字母开头、后跟小写字母并以空格结尾的单词。这是正确的思考方式吗?我没有意识到在 (?!) 括号内它总是在寻找单词的开头,这导致我的表达成功。
  • @mlikj2006 ^ 运算符只匹配行首。它与单词边界无关(\b)。否定的前瞻断言封闭的模式不能匹配(在当前位置)。如果正则表达式的一部分不能在当前位置匹配,它会在另一个位置尝试。像^ 这样的锚可以用来修复部分模式,这限制了这种行为。如果您不确定某个正则表达式功能,并且文档没有帮助,那么减少正则表达式并使用各种输入对其进行测试可以帮助您理解。
【解决方案2】:

只检查字符串的大小写字符怎么样?

(?=.*[A-Z])(?=.*[a-z])

如您所见,这不会匹配仅包含一种情况的字符串,因为两个前瞻必须匹配。

当然,这只是执行两个正则表达式匹配并组合结果的复杂方法:

if ($line =~ /[A-Z]/ and $line =~ /[a-z]/)

【讨论】:

  • 哇。直到我看到这个才意识到我的样子有多荒谬。谢谢
【解决方案3】:

这将匹配整个单词的混合大小写:

^[[:alpha:]]*([[:upper:]][[:lower:]]|[[:lower:]][[:upper:]])[[:alpha:]]*$

小一点:

^[A-Za-z]*([A-Z][a-z]|[a-z][A-Z])[A-Za-z]*$

【讨论】:

  • 使用 ^[a-zA-Z]+$ 匹配所有内容。有没有办法只匹配 asdasdfFFFdsfs
  • @mlikj2006 匹配该字符串而不是其他字符串的标准是什么?
猜你喜欢
  • 1970-01-01
  • 2020-06-30
  • 2021-10-11
  • 1970-01-01
  • 2011-10-14
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多