我该如何使用Java正则表达式实现这个?

4
尝试制作一个正则表达式,抓取所有不在括号中的单词,例如chicken。就像这样:
chicken

将被选择,但是

[chicken]

不会。有人知道如何做吗?

1
foo 什么时候过时的? :) - keyser
2
这只鸡可能已经过马路去见它了。无论如何,为了真正好的学习和练习正则表达式,我使用这个网站:http://gskinner.com/RegExr/ - android developer
4个回答

7
String template = "[chicken]";
String pattern = "\\G(?<!\\[)(\\w+)(?!\\])";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(template);

while (m.find()) 
{
     System.out.println(m.group());
}

它使用负回顾后断言和负前瞻断言以及边界匹配器的组合。
(?<!\\[) //negative look behind
(?!\\])  //negative look ahead
(\\w+)   //capture group for the word
\\G      //is a boundary matcher for marking the end of the previous match 

请阅读以下编辑以获得澄清:
编辑1: 如果需要考虑以下情况:
"chicken [chicken] chicken [chicken]"

我们可以用以下内容替换正则表达式:
String regex = "(?<!\\[)\\b(\\w+)\\b(?!\\])";

编辑2:
如果还需要考虑像这样的情况:
"[chicken"
"chicken]"

如果你仍然想要“鸡肉”,那么可以使用以下方式:
String pattern = "(?<!\\[)?\\b(\\w+)\\b(?!\\])|(?<!\\[)\\b(\\w+)\\b(?!\\])?";

这基本上解释了只在一侧有一个括号的两种情况。它通过使用 | 作为或运算符,并在前后查找后面添加 ? 来实现这一点,其中 ? 表示前面的表达式出现 0 次或 1 次。

为什么要使用.group(1)?为什么不直接去掉分组,使用.group()呢? - arshajii
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/34569/discussion-between-steve-p-and-arshajii - Steve P.
@arshajii 我认为在我的最终编辑中,我已经考虑到了所有可能的情况,但我不确定100%。 - Steve P.
它运行良好,但我有一个关于正则表达式的问题。 假设我有字符串“ The x chicken”,如何检查其中的“x”是任何字符串。 - PaulBGD
@Ultimate,我很高兴,但请确保您阅读了两个编辑部分,以防出现其中一个边缘情况。如果是简短的回答,我不介意回答,但如果不是,您应该提出另一个问题。 - Steve P.
显示剩余14条评论

2

我猜你想要类似以下内容:

final Pattern UNBRACKETED_WORD_PAT = Pattern.compile("(?<!\\[)\\b\\w+\\b(?!])");

private List<String> findAllUnbracketedWords(final String s) {
    final List<String> ret = new ArrayList<String>();
    final Matcher m = UNBRACKETED_WORD_PAT.matcher(s);
    while (m.find()) {
        ret.add(m.group());
    }
    return Collections.unmodifiableList(ret);
}

请注意,这不会匹配[chicken(只有一个[,没有])。 - Qtax
@Qtax: 是的,说得好。我不确定这是否是个问题;OP提供了很少的信息。(这就是为什么我的回答以“我猜你想要”开始的原因。:-P) - ruakh
你为什么不趁机把 findAllUnbracketedWords() 方法改成 public final 呢?;-p - Mr. Polywhirl

0

使用这个:

/(?<![\[\w])\w+(?![\w\]])/

即,连续的单词字符没有方括号或者在其前后有单词字符。

这需要同时检查左右是否有同时存在方括号和单词字符,否则对于你输入的[chicken]它只会简单地返回。

hicke

0

不用四处看:

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class MatchingTest
{
    private static String x = "pig [cow] chicken bull] [grain";

    public static void main(String[] args)
    {
        Pattern p = Pattern.compile("(\\[?)(\\w+)(\\]?)");
        Matcher m = p.matcher(x);
        while(m.find())
        {
            String firstBracket = m.group(1);
            String word = m.group(2);
            String lastBracket = m.group(3);
            if ("".equals(firstBracket) && "".equals(lastBracket))
            {
                System.out.println(word);
            }
        }
    }
}

输出:

pig
chicken

更加详细,当然,我认为这样更易读且更容易理解。肯定比尝试处理所有可能的括号组合的巨大正则表达式简单。

请注意,这不会过滤输入如[fence tree grass];它将指示tree是匹配的。您无法跳过其中的tree,除非使用解析器。希望这不是您需要处理的情况。


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