我正在尝试匹配任何不完全由大写字母或小写字母组成的单词,并且我写了以下正则表达式:
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的新手,我很困惑。
感谢。
答案 0 :(得分:3)
你陷入了多次否定和锚定的陷阱,而你得到的正则表达并没有完全按照自己的意愿行事。假设我们只有简化的正则表达式/(?!^[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的第二个解决方案更简单,可能更有效)
答案 1 :(得分:3)
如何只检查字符串中的大小写字符?
(?=.*[A-Z])(?=.*[a-z])
如您所见,这与仅包含一个案例的字符串不匹配,因为两个前瞻必须匹配。
当然,这只是执行两个正则表达式匹配并组合结果的复杂方法:
if ($line =~ /[A-Z]/ and $line =~ /[a-z]/)
答案 2 :(得分:1)
这将匹配整个单词的混合案例:
^[[:alpha:]]*([[:upper:]][[:lower:]]|[[:lower:]][[:upper:]])[[:alpha:]]*$
小一点:
^[A-Za-z]*([A-Z][a-z]|[a-z][A-Z])[A-Za-z]*$