【问题标题】:Extract sub-string between two certain words using regex in java在java中使用正则表达式提取两个特定单词之间的子字符串
【发布时间】:2011-08-15 08:28:47
【问题描述】:

我想使用 java 提取某些两个单词之间的子字符串。

例如:

This is an important example about regex for my work.

我想提取“an”和“for”之间的所有内容。

到目前为止我所做的是:

String sentence = "This is an important example about regex for my work and for me";
Pattern pattern = Pattern.compile("(?<=an).*.(?=for)");
Matcher matcher = pattern.matcher(sentence);

boolean found = false;
while (matcher.find()) {
    System.out.println("I found the text: " + matcher.group().toString());
    found = true;
}
if (!found) {
    System.out.println("I didn't found the text");
}

效果很好。

但我还想做两件事

  1. 如果句子是:This is an important example about regex for my work and for me. 我想提取到第一个“for”即important example about regex

  2. 有时我想将模式之间的单词数限制为 3 个单词,即important example about

有什么想法吗?

【问题讨论】:

  • 你想要模式只匹配 'an' 和 'for' 之间只有 3 个单词,还是只需要 3 个单词而不考虑匹配中的单词数?跨度>
  • @Dragon8:我只想要3个单词,不管匹配的单词数。
  • 好的,然后你可以用someString.split(" ")分割比赛。它返回一个字符串数组,每个位置都是匹配中的一个单词。

标签: java regex


【解决方案1】:

对于你的第一个问题,让它变得懒惰。你可以在量词后面加一个问号,然后量词会尽量少匹配。

(?<=an).*?(?=for)

我不知道最后的附加 ..*. 有什么好处是不必要的。

对于第二个问题,您必须定义“单词”是什么。我会说这里可能只是一个非空格序列,后跟一个空格。像这样的

\S+\s

像这样重复3次

(?<=an)\s(\S+\s){3}(?=for)

确保整个单词的模式数学使用单词边界

(?<=\ban\b)\s(\S+\s){1,5}(?=\bfor\b)

online here on Regexr

{3} 将精确匹配 3,最少为 1,最多为 3 这样做{1,3}

替代方案:

正如 dma_k 在您的案例中正确说明的那样,没有必要使用向后看和向前看。见here the Matcher documentation about groups

您可以改用捕获组。只需将要提取的部分放在括号中,它将被放入捕获组中。

\ban\b(.*?)\bfor\b

online here on Regexr

你可以像这样访问这个组

System.out.println("I found the text: " + matcher.group(1).toString());
                                                        ^

您只有一对括号,所以很简单,只需将1 放入matcher.group(1) 即可访问第一个捕获组。

【讨论】:

  • 我也建议不要使用向前/向后的语法。为什么要把事情复杂化? an\b(.*?)\bfor 将完美地完成这项工作。
  • 正如@dmk_k(谢谢)正确地指出在您的情况下没有必要在此处使用高级构造,我用更简单的解决方案更新了我的答案。
  • @stema:感谢您的帮助。第二种选择对我不起作用,我不知道为什么它找不到文本。另一件事我希望“an”成为单独的单词“an”而不是像“and”或“important”这样的单词的一部分。
  • @Daisy 我更新了我的解决方案,添加了\b 字边界。我还添加了“Regexr”的链接,这是一个很好的在线工具,您可以在其中测试您的正则表达式。
  • 但我想知道为什么这比向前/向后看更容易?我什么时候应该使用向前/向后看?
【解决方案2】:

您的正则表达式是“an\\s+(.*?)\\s+for”。它提取 an 和之间的所有字符以忽略空格 (\s+)。问号的意思是“贪婪”。需要防止.*模式吃掉包括“for”在内的所有东西。

【讨论】:

  • 问号使量词变得不贪婪。您的答案中缺少量词,因此您正在寻找任意字符并使用问号将其设为可选。
  • @AlexR:谢谢,它可以工作,但是像这样添加 *:"an\\s+(.*?)\\s+for"
【解决方案3】:

公共类 SubStringBetween {

public static String subStringBetween(String sentence, String before, String after) {

    int startSub = SubStringBetween.subStringStartIndex(sentence, before);
    int stopSub = SubStringBetween.subStringEndIndex(sentence, after);

    String newWord = sentence.substring(startSub, stopSub);
    return newWord;
}

public static int subStringStartIndex(String sentence, String delimiterBeforeWord) {

    int startIndex = 0;
    String newWord = "";
    int x = 0, y = 0;

    for (int i = 0; i < sentence.length(); i++) {
        newWord = "";

        if (sentence.charAt(i) == delimiterBeforeWord.charAt(0)) {
            startIndex = i;
            for (int j = 0; j < delimiterBeforeWord.length(); j++) {
                try {
                    if (sentence.charAt(startIndex) == delimiterBeforeWord.charAt(j)) {
                        newWord = newWord + sentence.charAt(startIndex);
                    }
                    startIndex++;
                } catch (Exception e) {
                }

            }
            if (newWord.equals(delimiterBeforeWord)) {
                x = startIndex;
            }
        }
    }
    return x;
}

public static int subStringEndIndex(String sentence, String delimiterAfterWord) {

    int startIndex = 0;
    String newWord = "";
    int x = 0;

    for (int i = 0; i < sentence.length(); i++) {
        newWord = "";

        if (sentence.charAt(i) == delimiterAfterWord.charAt(0)) {
            startIndex = i;
            for (int j = 0; j < delimiterAfterWord.length(); j++) {
                try {
                    if (sentence.charAt(startIndex) == delimiterAfterWord.charAt(j)) {
                        newWord = newWord + sentence.charAt(startIndex);
                    }
                    startIndex++;
                } catch (Exception e) {
                }

            }
            if (newWord.equals(delimiterAfterWord)) {
                x = startIndex;
                x = x - delimiterAfterWord.length();
            }
        }
    }
    return x;
}

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-13
    • 1970-01-01
    • 2017-04-15
    相关资源
    最近更新 更多