4

我在使以下正则表达式工作时遇到了一些问题。我想要以下字符串:

"Please enter your name here"

生成一个包含以下元素的数组:

'please enter', 'enter your', 'your name', 'name here'

目前,我正在使用以下模式,然后创建一个匹配器并以下列方式迭代:

Pattern word = Pattern.compile("[\w]+ [\w]+");
Matcher m = word.matcher("Please enter your name here");

while (m.find()) {
    wordList.add(m.group());
}

但我得到的结果是:

'please enter', 'your name'

我究竟做错了什么?(Ps,我在 regexpal.com 上检查了相同的正则表达式并遇到了同样的问题)。似乎同一个词不会匹配两次。我该怎么做才能达到我想要的结果?

谢谢。

---------------------------------

编辑: 感谢所有建议!我最终这样做了(因为它增加了能够轻松指定“n-gram”数量的灵活性):

Integer nGrams = 2;
String patternTpl = "\\b[\\w']+\\b";
String concatString = "what is your age? please enter your name."
for (int i = 0; i < nGrams; i++) {
    // Create pattern.
    String pattern = patternTpl;
    for (int j = 0; j < i; j++) {
        pattern = pattern + " " + patternTpl;
    }
    pattern = "(?=(" + pattern + "))";
    Pattern word = Pattern.compile(pattern);
    Matcher m = word.matcher(concatString);

    // Iterate over all words and populate wordList
    while (m.find()) {
        wordList.add(m.group(1));
    }
}

这导致:

Pattern: 
(?=(\b[\w']+\b)) // In the first iteration
(?=(\b[\w']+\b \b[\w']+\b)) // In the second iteration

Array:
[what, is, your, age, please, enter, your, name, what is, is your, your age, please enter, enter your, your name]

注意:从以下最佳答案中获得模式:Java regex skipping matches

4

4 回答 4

7

比赛不能重叠,这解释了你的结果。这是一个潜在的解决方法,利用具有积极前瞻性的捕获组

Pattern word = Pattern.compile("(\\w+)(?=(\\s\\w+))");
Matcher m = word.matcher("Please enter your name here");

while (m.find()) {
    System.out.println(m.group(1) + m.group(2));
}
请输入
输入您的
你的名字
在此取名
于 2013-09-11T21:24:43.957 回答
1

如果您想避免使用此类特定的 RegEx,也许您应该尝试一个更简单、更容易的解决方案:

public static String[] array(final String string){
    final String[] words = string.split(" ");
    final String[] array = new String[words.length-1];
    for(int i = 0; i < words.length-1; i++)
        array[i] = String.format("%s %s", words[i], words[i+1]);
    return array;
}

public static void main(String args[]){
    final String[] array = array("Please enter your name here");
    System.out.println(Arrays.toString(array));
}

输出是:

[Please enter, enter your, your name, name here]

于 2013-09-11T21:33:01.990 回答
0

你没有做错什么。这只是正则表达式的工作方式(否则匹配将变为 O(n^2),因为正则表达式匹配是在线性时间内完成的,因此无法处理)。

在这种情况下,您可以简单地搜索[\w]+. 并对这些组进行后处理。

于 2013-09-11T21:24:25.667 回答
0

就像是:

Pattern word = Pattern.compile("(\\w+) ?");
Matcher m = word.matcher("Please enter your name here");

String previous = null;
while (m.find()) {
    if (previous != null)
        wordList.add(previous + m.group(1));
    previous = m.group();
}

模式以可选空格结尾(如果字符串中有更多空格,则匹配)。 m.group()返回整个匹配,带空格;m.group(1)只返回单词,没有空格。

于 2013-09-11T21:31:36.467 回答