10

目标: 我想分隔单词以计算它们在文档中的频率,然后对这些频率进行一些计算。

单词可以以以下任何内容开始/包含/结束:

  • 数字
  • 字母(包括 é、ú、ó 等,但不包括 $、#、& 等符号)

单词可以包含(但不能以开头或结尾)

  • 下划线(例如:rishi_dua)
  • 单引号(例如:不能)
  • 连字符(例如:123-)

单词可以用任何符号或空格分隔,如 $、#、&、制表符

问题:

  1. 在不匹配其他特殊字符的情况下,我无法找出如何匹配 é、ú、ó 等。
  2. 什么是更有效的方法来做到这一点(可选
  3. 目前按空间分割对我有用,因为没有其他方法

我试过的:

方法: 首先我将除 \w(字母数字加“_”)、' 和 - 之外的所有内容替换为空格然后删除 '、_ 和 '(如果在单词的开头或结尾找到)最后我将多个空格替换为单个空格并拆分单词

代码: 我正在使用一系列正则表达式替换如下:

$str =~ s/[^\w'-]/ /g;
#Also tried using $str =~ s/[^:alpha:0-9_'-]/ /g; but doesn't work
$str =~ s/- / /;
$str =~ s/' / /;
$str =~ s/_ / /;
$str =~ s/ -/ /;
$str =~ s/ '/ /;
$str =~ s/ _/ /;

$str =~ s/ +/ /;
foreach $word (split(' ', lc $str)) {
    #do something
}

约束: 我必须在 Perl 中执行(因为这是我在 Perl 中编写的较大代码的一部分),但我可以使用除 Regex 之外的其他选项

4

3 回答 3

17

您可以使用\p{L}匹配所有字母的字符类。并使用\P{L}匹配所有非字母的。

要允许引用和连字符,您可以使用:

\p{L}[\p{L}'_-]*\p{L}+(?:['_-]\p{L}+)*避免在边界处使用非字母。

注意:有些重音字符用多个码点表示,例如,即使存在一个码点表示à(agrave),也可以用两个码点组成:ascii 字母a和组合字符`(重音)。\p{L}\p{Mn}*可以匹配这些字形:

(?>\p{L}\p{Mn}*)+(?:['_-](?>\p{L}\p{Mn}*)+)*

使用拆分方法更加危险和困难 IMO,特别是如果您想处理组合字符。但基本上要匹配您可以使用的分隔符:

[^\p{L}\p{Mn}'_-]+

或者更明确地说:

[^\p{L}\p{Mn}'_-]+|(?<![\p{L}\p{Mn}])['_-]+|[-_']+(?!\p{L})在没有被字母包围的连字符和引号上分开。

于 2013-07-05T02:15:50.813 回答
2

阅读Tom Christiansen为什么现代 Perl 默认避免使用 UTF-8 的非常详细的回答?. 对您的问题的简短回答是,您必须确保正确解码和编码文本,并且您必须了解如何使用 Perl 正则表达式模式来匹配 Unicode 文本。

于 2013-07-05T02:25:40.250 回答
0

您可能会发现这个 cpan 模块很有趣。我以前用过它,对我来说效果很好。它可以用来简单地从字符中删除重音:

http://search.cpan.org/~pjacklam/Text-Unaccent-PurePerl-0.05/lib/Text/Unaccent/PurePerl.pm

于 2013-07-05T05:53:53.567 回答