使用一个正则表达式将整个文本拆分为单词

时间:2016-04-29 14:53:50

标签: java regex string split

我正在寻找问题的解决方案。我需要为任何给定的文本创建一种创建单词列表和只是单词的方法,包括非英文字母和特殊字符。我搜索了很多,我正在阅读文档here,但这对我来说并不完美。其中最好的是这一个:

String line = "    W metal, w liczbę, w trupie ciało, -"
String[] words = line.split("\\P{javaLetter}+");
    for (int i = 0; i < words.length; i++) {
        if (!words[i].equals("")) {  // I don't want to check everytime
            anotherList.add(word[i].toLowerCase())
        }
    }
}

但结果是:

["", "W", "metal", "w", "liczbę", "w", "trupie", "ciało"]

String开头的这个空格打破了我的正则表达式。 哪个是使用拉丁字母在任何语言中制作单词的正确正则表达式(不关心英语单词中的撇号)?

3 个答案:

答案 0 :(得分:2)

您可以使用相反的方法 - 匹配:

List<String> words = new ArrayList<>();
String line = "    W metal, w liczbę, w trupie ciało, -";
Matcher m = Pattern.compile("\\p{L}+").matcher(line);
while (m.find()) {
    words.add(m.group());
}
System.out.println(words); // => [W, metal, w, liczbę, w, trupie, ciało]

请参阅IDEONE demo\\p{L}+将匹配任何Unicode字母的1+。

有一种方法可以使用拆分方法,但我们需要先对输入字符串进行预处理:

String line = "    W metal, w liczbę, w trupie ciało, -";
String[] words = line.replaceFirst("^\\P{L}+", "").split("\\P{L}+");
System.out.println(Arrays.toString(words));

请参阅another IDEONE demo

.replaceFirst("^\\P{L}+", "")将从字符串的开头删除所有非字母符号,因此,在分割数组中不会留下空元素。

答案 1 :(得分:0)

假设您希望words的结果与anotherList相同,但不会在循环中对结果进行后处理。那么一些预处理呢?

String line = "    W  metal,  w  liczbę,   w  trupie ciało, -";
String[] words = line.trim().toLowerCase().split("\\P{javaLetter}+");
System.out.println(Arrays.toString(words));

结果:[w, metal, w, liczbę, w, trupie, ciało]

答案 2 :(得分:0)

首先,我添加了其变体中的单引号。然后是所有字母,以及与字母组合的零宽度重音符。

String[] rawWords = line.trim().split("(?U)[^\\p{L}\\p{M}'\u0060\u00b4\u2017]");

查看正则表达式的Pattern的javadoc。

如果该行不以单词开头,则不会阻止前面的空单词。这也可以替换,但检查就足够了。

另一个问题是,每个单引号都被认为是单词的一部分。 这可以通过删除所有前导和尾随的单词引号序列来完成。

我不会尝试制作一个单一的正则表达式,虽然这对引用问题肯定是可能的。

一种简化是使用Unicode文本规范化。 "ŝ"可以是一个字符\u0150或两个字符c加上零宽度^。这可以通过课程java.text.Normalizer完成。如果您使用组合表单,则无法再使用\\p{M}。 所有这些单引号都可以替换为撇号'

(对于自然语言处理,可能会对JNLP感兴趣。)