6

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

我已经在正则表达式上测试了我的正则表达式,但 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");
        }
    }
4

6 回答 6

3
  1. 在 Java 中,要将\b 单词边界传递给正则表达式引擎,您需要将其编写为\\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*在开头添加,如果子字符串也应该在单词中间匹配(不仅在开头)。

所以你的代码看起来像

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();
}
于 2013-07-27T20:54:56.673 回答
2

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

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;
}

当然,这样做将有效地通过您的输入字符串进行两次传递,这毫无价值。第一遍查找要拆分的空白字符,第二遍查找子字符串的每个拆分词。

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

于 2013-07-27T20:56:52.537 回答
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
于 2013-07-27T21:01:24.570 回答
1

模式应该是

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

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

于 2013-07-27T21:02:32.513 回答
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());
}
于 2013-07-27T21:03:53.300 回答
0

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

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



就这样。

于 2013-07-27T21:20:08.857 回答