匹配除了特定字符串以外的所有大写字符的正则表达式

6
我想匹配所有包含任何大写字母但忽略字符串 A_ 的行。
为了增加复杂性,我想忽略不同字符串之后的一切,例如打开注释。
这里是应该匹配和不应该匹配的示例: 匹配: - fooBar - foo Bar foo - A_fooBar - fooBar /* Comment */ 不匹配(C_不应触发匹配):
- A_foobar - foo A_bar - foobar - foo bar foo bar - foobar /* Comment */
谢谢 :)

A_fooBar中包含一个A_,并且在匹配项中列出,我不理解(特别是因为A_foobar被列为不匹配)。 - C. Ross
我正在使用PowerGrep进行此测试。@ C. Ross,A_fooBar是匹配的,因为bar中有B,而不是A_。 - Alan
6个回答

5
这应该也可以(吗):
(?!A_)[A-Z](?!((?!/\*).)*\*/)

一个简短的说明:
(?!A_)[A-Z]     # if no 'A_' can be seen, match any uppercase letter
(?!             # start negative look ahead
  ((?!/\*).)    #   if no '/*' can be seen, match any character (except line breaks)
  *             #   match zero or more of the previous match
  \*/           #   match '*/'
)               # end negative look ahead

因此,用通俗易懂的语言来说:
匹配任何大写字母,但不包括'A_',同时如果在没有先遇到'/*'的情况下出现了'*/',则不包括大写字母。

1

尝试:

(?<!A_)[a-zA-Z]+

(?!...) 被称为 负向预测先行断言

至于你的具体问题,这有点作弊,但可以尝试:

^([#\.]|(?<!A_))[A-Za-z]{2,}

我得到:
fooBar => fooBar
foo Bar foo => foo
A_fooBar (no match)
fooBar /* Comment */ => fooBar
A_foobar (no match)
foo A_bar => foo
foobar => foobar
foo bar foo bar => foo
foobar /* Comment */ => foobar

谢谢,但我不想匹配 [a-zA-Z]。这是我目前的正则表达式 ^([A-Z]|[#.])[^{]*?(?<=[A-Z]),现在我需要排除任何只有 A_ 作为它们唯一大写字符的匹配项。 - Alan
那个表达式没有太多意义。我正在进行一个小测试,它只匹配前面带有A的那些。 - cletus
表达式仅匹配大写字符,它检查行的开头,并允许以#或.(像CSS一样)[A-Z] | [#.]。然后,它找到除了{之外的任何内容,停止并向后查找任何大写字符。这对我很有效。我现在唯一的问题是,当它回望时看到A_时防止匹配。 - Alan

1

我的答案:

/([B-Z]|A[^_]|A$)/

如果可能的话,我会在较早的阶段删除评论。

测试:

#!perl
use warnings;
use strict;

my @matches = (
"fooBar",
"foo Bar foo",
"A_fooBar",
"fooBar /* Comment */");

my @nomatches = (
"A_foobar",
"foo A_bar",
"foobar",
"foo bar foo bar",
"foobar /* Comment */");

my $regex = qr/([B-Z]|A[^_]|A$)/;

for my $m (@matches) {
    $m =~ s:/\*.*$::;
    die "FAIL $m" unless $m =~ $regex;
}
for my $m (@nomatches) {
    $m =~ s:/\*.*$::;
    die "FAIL $m" unless $m !~ $regex;
}

尝试一下:http://codepad.org/EJhWtqkP

谢谢Kinopiko,我喜欢你的解决方案的简洁性。我正在编写用于静态代码分析的表达式,因此我实际上不会删除任何内容。这就是为什么我不想在注释中进行匹配的原因。 - Alan
只需复制该字符串并在复制的字符串上执行匹配操作。 - user181548

0

这个可以做到,尽管注释处理不是非常健壮。(它假设注释总是在行末。)

.*((A(?!_)|([B-Z]))(?<!/\*.*)).*\r\n

这看起来非常有前途,Mike,谢谢。我认为当有多个_时它会出现问题,我还在研究中。 - Alan

0

试试这个:

^(?:[^A-Z/]|A_|/(?!\*))*+[A-Z]

这将适用于任何支持占有量词的版本,例如PowerGrep、Java和PHP。.NET版本不支持,但它支持原子组:

^(?>(?:[^A-Z/]|A_|/(?!\*))*)[A-Z]

如果这两个特性都不可用,您可以使用另一个前瞻来防止它在回弹时匹配 A_

^(?:[^A-Z/]|A_|/(?!\*))*(?!A_)[A-Z]

0

它必须是一个单一的正则表达式吗?在Perl中,您可以这样做:

if ($string =~ /[A-Z]/ && $string !~ /A_/)

虽然不如具有回溯的单个表达式那么酷,但可能更易于阅读和维护。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接