2

我的问题很简单。对于那些熟悉 RegEx 的人来说很简单,不幸的是,我不是。所以,请帮我解决这个问题。

我有String。比方说,"java @aa@ test @bbb@"。如果我需要的唯一匹配项是,我应该使用什么正则表达式:

1. @aa@
2. @bbb@

我尝试了这个表达式(@(.*)@),但结果是:

1. "@aa@ bang @bb@
2. aa@ bang @bb

这离我需要的太远了。

PS 另外,我不希望在这两个 @ 符号内匹配 @@ 或空字符串。

4

4 回答 4

2

在我看来,最好的选择是

@[^@]+@

看起来像:

正则表达式可视化

调试演示

可以使用 non-greedy .+?,但是当您的分隔符只有一个字符(在这种情况下@)时,您通常应该更喜欢否定字符类方法。

顺便说一句,学习正则表达式的一个很好的资源是regular-expressions.info。它从最基本的开始,一直到非常高级。如果您有兴趣了解有关正则表达式的更多信息,我敦促您浏览一下。当然,还有关于正则表达式的特定于 Java 的 Oracle 课程;两者都很棒。


String str = "java @aa@ test @bbb@";

Matcher m = Pattern.compile("@[^@]+@").matcher(str);
while (m.find())
    System.out.println(m.group());
@aa@
@bbb@
于 2013-10-12T15:23:43.387 回答
2

.* 是贪婪的。你应该试试 。*?

如果你把 ? 那么 reg exp 将在第一个 @ 处停止,否则它不会停止,直到它匹配最后一个 @(这是贪婪)

于 2013-10-12T15:23:55.013 回答
1

量词默认是贪婪的。.*将消耗一切直到最后@。为了让它停在第一个@,你需要使用不情愿的量词:

@.+?@

或者也可以使用否定字符类:

@[^@]+@
于 2013-10-12T15:23:24.960 回答
1

两种选择:使用非贪婪或使用否定类。

非贪婪是通过在 中添加 a?来实现的.*

@(.*?)@

否定类正在使用所有内容而不是@

@([^@]*)@

顺便说一下,第二个更快。

其实还有第三种方式:

(?<=@)[^@]*(?=@)

但这可能有点难以理解。


在我看来,您不太了解正则表达式。也许需要更多的解释。

.in regex 将匹配任何字符,除非它被转义或在将被视为文字字符的字符类中使用。

*在 regex 中是一个量词,它允许前一个模式匹配 0 次或更多次;这意味着如果没有可匹配的内容,则将匹配“无”,并且在您的情况下,将匹配两者之间的任何内容,@以便@@您得到一个空字符串作为结果。

+类似于*,除了匹配 0 次或多次,而是匹配 1 次或多次,这意味着它确保至少有 1 个字符要匹配。在您的情况下,将第二个正则表达式(带有否定类)与此量词一起使用会更有意义:@([^@]+)@

( ... )是一个捕获组,如果有匹配,它将存储里面的内容。尽量限制这些的使用,因为它会消耗更多的内存,否则你的脚本/程序会在没有它的情况下使用。

[ ... ]是一个字符类,它将匹配里面提到的任何字符。很多正则表达式元字符在内部失去了意义,字符类有自己的元字符:^如果放在字符类的开头,这意味着与字符相反;并且-表示一系列字符,如果它没有被排除或在字符类的末端。

[^ ... ]如上所述是一个否定类,它将匹配除字符类中的所有字符之外的所有字符。

(?= ... )是一个积极的前瞻,只有当里面的模式与前一个匹配之后的匹配时才允许匹配,而不将它们计入匹配本身。

(?<= ... )是一个正向的lookbehind,仅当内部的模式与下一个匹配之前的匹配时才允许匹配,而不将它们计入匹配本身。


从这些中,如果您不想得到空匹配,请使用:

@([^@]+)@

或者:

(?<=@)[^@]+(?=@)

由于@(.+?)@表单也将允许@匹配字符。

于 2013-10-12T15:23:54.183 回答