如何仅从任意输入文件中提取字母单词
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 个或多个否定类别。
这只是一个普通的配方,复杂的情况可能需要不同的方法。
我正在写一个拼写检查器,我必须只提取单词(由字母构成)。我在使用多个定界符时遇到问题。 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 个或多个否定类别。
这只是一个普通的配方,复杂的情况可能需要不同的方法。