【问题标题】:regex last word in a sentence ending with punctuation (period)正则表达式以标点符号结尾的句子中的最后一个单词(句点)
【发布时间】:2013-09-12 10:25:38
【问题描述】:

我正在寻找正则表达式模式,而不是 Java 代码,以匹配英语(或欧洲语言)句子中的最后一个单词。如果在这种情况下最后一个词是“hi”,那么我想匹配“hi”而不是“hi”。

正则表达式(\w+)\.$ 将匹配“hi.”,而输出应该只是“hi”。什么是正确的正则表达式?

thufir@dur:~/NetBeansProjects/regex$ 
thufir@dur:~/NetBeansProjects/regex$ java -jar dist/regex.jar 


trying
a b cd efg hi
matches:
hi


trying
a b cd efg hi.
matches:
thufir@dur:~/NetBeansProjects/regex$ 

代码:

package regex;

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

public class Main {

    public static void main(String[] args) {
        String matchesLastWordFine = "a b cd efg hi";
        lastWord(matchesLastWordFine);
        String noMatchFound = matchesLastWordFine + ".";
        lastWord(noMatchFound);
    }

    private static void lastWord(String sentence) {
        System.out.println("\n\ntrying\n" + sentence + "\nmatches:");
        Pattern pattern = Pattern.compile("(\\w+)$");
        Matcher matcher = pattern.matcher(sentence);
        String match = null;
        while (matcher.find()) {
            match = matcher.group();
            System.out.println(match);
        }
    }
}

我的代码是用 Java 编写的,但这既不是这里也不是那里。我正在严格寻找正则表达式,而不是 Java 代码。 (是的,我知道用 Java 可以去掉最后一个字符。)

我应该在模式中加入什么正则表达式?

【问题讨论】:

  • 您在代码中使用的正则表达式中没有\.。您的正则表达式对我来说是正确的,捕获组将包含不带句点的单词。
  • 等等,所以你要匹配行中的最后一个单词。如果该行以句号结尾,那么您不想有句号吗?
  • @Taemyr 完全正确。如果有句号,那就是最后一个字。
  • 我已经更新了我的答案以反映这一点。
  • @cyon LOL,是的,我不明白。看看我对你所说的做的回答(虽然我一开始不明白你的意思)。

标签: java regex


【解决方案1】:

您可以使用前瞻断言。例如匹配没有句点的句子:

[\w\s]+(?=\.)

[\w]+(?=\.)  

最后一个单词(“.”之前的单词)

【讨论】:

  • [\w]+(?=\.) 是我正在寻找的特定位。我将研究前瞻断言的含义。
【解决方案2】:

如果您需要将整个匹配作为最后一个单词,您可以使用前瞻。

\w+(?=(\.))

这匹配一组后跟句点的单词字符,而不匹配句点。

如果你想要一行中的最后一个单词,无论该行是否在句尾结束,你都可以使用:

\w+(?=(\.?$))

或者,如果您还想包含 ,!;: 等

\w+(?=(\p{Punct}?$))

【讨论】:

    【解决方案3】:

    您可以使用matcher.group(1) 获取第一个捕获组的内容(在您的情况下为(\w+))。多说一点,matcher.group(0) 会返回给你完整的比赛。所以你的正则表达式几乎是正确的。一项改进与您对$ 的使用有关,这将赶上行尾。仅当您的句子完全填满时才使用它!

    【讨论】:

      【解决方案4】:

      使用此正则表达式 (\w+)\p{Punct},您将获得 1 组计数,这意味着您将在 matcher.group(0) 获得一组带标点符号的组,在 matcher.group(1) 获得一组不带标点符号的组。

      要在 Java 中编写正则表达式,请使用:"(\\w+)\\p{Punct}"

      要使用 Java(实际上还有很多其他语言)在线测试您的正则表达式,请参阅 RegexPlanet

      【讨论】:

      • 我认为这可能是解决问题的更好途径,但是,不,对不起,这不是我想要的。这将返回“嗨”。而我只想要“hi”没有点。如果不清楚,请原谅。但是,\p 语法非常有趣:)
      • 对于“test1, test2 test3”,它返回“test1”。我希望,这就是被问到的。为了澄清这一点:matcher.group(1)包含没有标点符号的单词(“hi”,而不是“hi.”)。还是那个“嗨”。可以在matcher.group(0)找到。
      【解决方案5】:

      通过使用 $ 运算符,您只会在行尾获得匹配项。因此,如果您在一行中有多个句子,您将不会在中间的句子中找到匹配项。

      所以你应该只使用:

      (\w+)\.
      

      捕获组将给出正确的匹配。

      你可以看一个例子here

      【讨论】:

      • 将匹配“hi.”,而我想要的输出只是“hi”没有点。抱歉,如果不清楚。
      【解决方案6】:

      我真的不明白为什么,但这有效:

      package regex;
      
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;
      
      public class Main {
      
          public static void main(String[] args) {
              String matchesLastWordFine = "a b cd efg hi";
              lastWord(matchesLastWordFine);
              String noMatchFound = matchesLastWordFine + ".";
              lastWord(noMatchFound);
          }
      
          private static void lastWord(String sentence) {
              System.out.println("\n\ntrying\n" + sentence + "\nmatches:");
              Pattern pattern = Pattern.compile("(\\w+)");  //(\w+)\.
              Matcher matcher = pattern.matcher(sentence);
              String match = null;
              while (matcher.find()) {
                  match = matcher.group();
              }
              System.out.println(match);
          }
      }
      

      我猜正则表达式 \w+ 将匹配所有单词 (doh)。然后最后一句话就是我所追求的。太简单了,真的,我试图排除标点符号,但我猜正则表达式会自动为你做到这一点..?

      【讨论】:

      • 之所以有效,是因为 matcher 找到了所有匹配项。而你的 while 循环遍历所有这些。因此,一旦这个循环完成,它就会指向最后一个单词。请参阅下面的答案,了解如何使用前瞻来匹配匹配后应遵循的条件。或者使用组来只保留部分匹配。
      猜你喜欢
      • 2015-06-19
      • 1970-01-01
      • 1970-01-01
      • 2021-05-07
      • 1970-01-01
      • 1970-01-01
      • 2016-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多