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

How to extract letter words only from an arbitrary input file

我正在写一个拼写检查器,我必须只提取单词(由字母构成)。我在使用多个定界符时遇到问题。 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 

我知道分词器,但我们只能使用扫描器。

有一个词提取元字符:\w。它选择所有被认为是单词的东西。

如果您只对单词 boundarys 感兴趣,您可以使用 \b,它应该适合作为分隔符。

参见http://www.vogella.com/tutorials/JavaRegularExpressions/article.html(第 3.2 章)

Scanner中的模式应该是一个正则表达式,描述所有你不想包含在标记中的字符,重复一次或多次(这最后一部分是因为这个词可能是由多个 space/punctuation 等分隔)

这意味着你需要一个模式来描述不是字母的东西。正则表达式使您能够否定 class 个字符。所以如果一个字母是[a-zA-Z],一个"non-letter"就是[^a-zA-Z]。所以可以用[^a-zA-Z]+来描述“1个或多个非字母”。

同样的事情还有其他的表达方式。 \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 个或多个否定类别。

这只是一个普通的配方,复杂的情况可能需要不同的方法。