如何仅从任意输入文件中提取字母单词

时间:2015-09-27 18:02:12

标签: java delimiter

我正在编写一个拼写检查器,我只需要提取单词(由字母构造)。我在使用多个分隔符时遇到问题。 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 

我知道令牌机,但我们只能使用扫描仪。

2 个答案:

答案 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章)