我正在编写一个拼写检查器,我只需要提取单词(由字母构造)。我在使用多个分隔符时遇到问题。 Java文档指定了几个分隔符的使用,但是我遇到了麻烦,包括每个不是字母的打印字符。
in_file.useDelimiter("., !?/@#$%^&*(){}[]<>\\\"'");
在这种情况下 - 运行时间
Exception in thread "main" java.util.regex.PatternSyntaxException:
Unclosed character class near index 35
我尝试使用
等模式("\s+,|\s+\?|""|\s:|\s;|\{}|\s[|[]|\s!");
运行时间 -
Exception in thread "main" java.util.regex.PatternSyntaxException:
Illegal repetition
我知道令牌机,但我们只能使用扫描仪。
答案 0 :(得分:2)
Scanner
中的模式应该是一个正则表达式,描述您不想包含在令牌中的所有字符,重复一次或多次(最后一部分是因为该单词可能被分隔不止一个空格/标点等。)
这意味着您需要一个描述不是字母的图案。正则表达式使您能够否定一类字符。因此,如果字母为[a-zA-Z]
,则“非字母”为[^a-zA-Z]
。因此,您可以使用[^a-zA-Z]+
来描述“一个或多个非字母”。
还有其他方法可以表达同样的事情。 \p{Alpha}
与[a-zA-Z]
相同。你通过大写P:\P{Alpha}+
来否定它。
如果您的文件包含非英文单词,那么您可能需要使用Unicode类别:\P{L}+
(意思是:1个或多个不是Unicode字母的字符)。
演示:
Scanner sc = new Scanner( "Hello, 123 שלום 134098ho こんにちは 'naïve,. 漢字 +?+?+مرحبا.");
sc.useDelimiter("\\P{Alpha}+");
while ( sc.hasNext()) {
System.out.println(sc.next());
}
输出:
Hello ho na ve
这是因为我们只要求US-ASCII字母表(\p{Alpha}
)。所以它打破了naïve
这个词,因为ï不是US-ASCII范围内的字母。它也忽略了其他语言中的所有单词。但是如果我们使用:
Scanner sc = new Scanner( "Hello, 123 שלום 134098ho こんにちは 'naïve,. 漢字 +?+?+مرحبا.");
sc.useDelimiter("\\P{L}+");
while ( sc.hasNext()) {
System.out.println(sc.next());
}
然后我们使用了unicode类别,输出将是:
Hello שלום ho こんにちは naïve 漢字 مرحبا
它为您提供所有语言的所有单词。所以这是你的选择。
<强>摘要强>
创建一个Scanner
分隔符,允许您获取由特定类别的字符组成的所有字符串(在本例中为字母):
+
以表示1个或多个否定类别。这只是一个常见的配方,复杂的情况可能需要不同的方法。
答案 1 :(得分:1)
词汇提取有一个元字符:\w
。它选择被认为是单词的所有内容。
如果您只对单词 boundarys 感兴趣,可以使用\b
,这应该适合作为分隔符。
见http://www.vogella.com/tutorials/JavaRegularExpressions/article.html(第3.2章)