我正在寻找问题的解决方案。我需要为任何给定的文本创建一种创建单词列表和只是单词的方法,包括非英文字母和特殊字符。我搜索了很多,我正在阅读文档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开头的这个空格打破了我的正则表达式。 哪个是使用拉丁字母在任何语言中制作单词的正确正则表达式(不关心英语单词中的撇号)?
答案 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));
.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感兴趣。)