提取包含某个子字符串的每个完整单词

时间:2013-07-27 20:49:54

标签: java regex

我正在尝试编写一个函数,从包含某个子字符串的句子中提取每个单词,例如在'Porky Pork Chop'寻找'Po'将返回Porky Pork。

我在regexpal上测试了我的正则表达式,但Java代码似乎不起作用。我做错了什么?

private static String foo()
    {

        String searchTerm = "Pizza";
        String text = "Cheese Pizza";

        String sPattern =  "(?i)\b("+searchTerm+"(.+?)?)\b";
        Pattern pattern = Pattern.compile ( sPattern );
        Matcher matcher = pattern.matcher ( text );
        if(matcher.find ())
        {
            String result = "-";
            for(int i=0;i < matcher.groupCount ();i++)
            {
                result+= matcher.group ( i ) + " ";
            }
            return result.trim ();
        }else
        {
            System.out.println("No  Luck");
        }
    }

6 个答案:

答案 0 :(得分:3)

  1. 在Java中将\b word boundaries传递给regex引擎,您需要将其写为\\b\b表示String对象中的退格。

  2. 根据您的示例判断,您希望返回包含子字符串的所有单词。要执行此操作,请不要使用for(int i=0;i < matcher.groupCount ();i++),而是使用while(matcher.find()),因为组计数将在单个匹配中迭代所有组,而不是在所有匹配上。

  3. 如果您的字符串可以包含一些特殊字符,您可能应该使用Pattern.quote(searchTerm)

  4. 在您的代码中,您试图在"Pizza"中找到"Cheese Pizza",因此我假设您还希望找到与搜索到的子字符串相同的字符串。虽然您的正则表达式可以正常使用,但您可以将上一部分(.+?)?)更改为\\w*,并在开头添加\\w*,如果子字符串也应该在单词的中间匹配(不仅在开始)。

  5. 所以你的代码看起来像

    private static String foo() {
    
        String searchTerm = "Pizza";
        String text = "Cheese Pizza, Other Pizzas";
    
        String sPattern = "(?i)\\b\\w*" + Pattern.quote(searchTerm) + "\\w*\\b";
        StringBuilder result = new StringBuilder("-").append(searchTerm).append(": ");
    
        Pattern pattern = Pattern.compile(sPattern);
        Matcher matcher = pattern.matcher(text);
        while (matcher.find()) {
            result.append(matcher.group()).append(' ');
        }
        return result.toString().trim();
    }
    

答案 1 :(得分:2)

虽然正则表达式方法当然是一种有效的方法,但我发现当你用空格分割单词时更容易思考。这可以使用String的{​​{3}}方法完成。

public List<String> doIt(final String inputString, final String term) {
    final List<String> output = new ArrayList<String>();
    final String[] parts = input.split("\\s+");
    for(final String part : parts) {
        if(part.indexOf(term) > 0) {
            output.add(part);
        }
    }
    return output;
}

当然,实现这一目标实际上是通过输入String进行两次传递是没有价值的。第一个找到要拆分的空格的字符,第二个遍读查看子字符串的每个拆分字。

如果需要一次通过,则正则表达式路径更好。

答案 2 :(得分:1)

我发现 nicholas.hauschild 的答案是最好的。

但是如果你真的想使用正则表达式,你可以这样做:

String searchTerm = "Pizza";
String text = "Cheese Pizza";
Pattern pattern = Pattern.compile("\\b" + Pattern.quote(searchTerm)
        + "\\b", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
    System.out.println(matcher.group());
}

输出:

Pizza

答案 3 :(得分:1)

模式应该是

String sPattern =  "(?i)\\b("+searchTerm+"(?:.+?)?)\\b";

您想要捕获整个(披萨)字符串。?:确保您不会捕获字符串的一部分两次。

答案 4 :(得分:0)

尝试这种模式:

String searchTerm = "Po";
String text = "Porky Pork Chop oPod zzz llPo";

Pattern p = Pattern.compile("\\p{Alpha}+" + substring + "|\\p{Alpha}+" + substring + "\\p{Alpha}+|" + substring + "\\p{Alpha}+");

Matcher m = p.matcher(myString);

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

答案 5 :(得分:0)

好的,我给你一个原始风格的模式(不是java风格,你必须自己双倍逃避):

(?i)\b[a-z]*po[a-z]*\b



这就是全部。