1

在 Windows 7 上使用 ActiveState Perl 5.14.2 或在 CentOS 6.3 Linux 上使用 Perl 5.10.1 我试图从 UTF8 文本中提取所有小写单词:

#!/usr/bin/perl -w

use strict;
use warnings;

while(<>) {
    # print "$1\n" while /\b([a-z]{3,})\b/g;
    print "$1\n" while /\b([\x{0430}-\x{044F}]{3,})\b/g;
}

虽然这对英文单词很有效(请参阅上面的注释行),但对于西里尔字母(请参阅Unicode 范围图表)则失败 - 脚本不会打印任何内容。

请问有人知道,有什么问题吗?

为方便起见,下面粘贴了一个示例俄语文本:

Все смешалось в доме Облонских。Жена узнала, что муж был в связи с бывшею в их доме француженкою-гувернанткой, и объя вила мужу, что не может жить Положение это продолжалось уже третий день и мучительно чувствовалось и самими супругами, и всеми членами семьи, и домось

4

2 回答 2

2

您指的是范围 >255 ( \x{0430}),这是内部 Perl unicode 格式。但是你的字符串似乎没有转换成那种格式。您需要设置use utf8;编译指示。这对我有用:

#!/usr/bin/perl -w

use strict;
use warnings;
use utf8;

binmode(STDOUT, ":utf8"); #Fix stdout warning

while(<DATA>) {
    print lc($1)."\n" while /\b([\x{0430}-\x{044F}]{3,})\b/g;
}
__DATA__
Все смешалось в доме Облонских. Жена узнала, что муж был.
в связи с бывшею в их доме француженкою-гувернанткой, и объявила мужу, что не может жить с ним в одном доме.
Положение это продолжалось уже третий день и мучительно чувствовалось и самими супругами, и всеми членами семьи, и домочадцами.

但更正确的方法是操作字符,而不是范围。此外,如果您从某个文件中读取,您可能需要设置 utf8 标志:

#!/usr/bin/perl -w

use strict;
use warnings;
use utf8;

binmode(STDOUT, ":utf8");

while(<>) {
    utf8::decode($_); #Convert into internal utf8 format
    print lc($1)."\n" while /\b([а-яА-ЯёЁ]{3,})\b/g;
}

Файл:

Однажды в студёную зимнуюю пору... ёёёёЁЁЁ йййЙЙЙЙ
Приветт, земляк!

如果启用use utf8 lc()将知道小写字母。

ёЁ是分开的,因为它是变音符号并且不适合范围)

于 2013-03-11T15:18:28.353 回答
0

您需要将 STDIN 和 STDOUT 设置为 UTF-8:

binmode STDOUT, ':utf8';
binmode STDIN, ':utf8';

您的正则表达式应该在此之后工作。

也就是说,我将使用 Unicode 属性测试的组合而不是显式范围:

\b(((?=\p{Cyrillic})\p{Lowercase_Letter}){3,})\b
于 2013-03-11T15:03:48.077 回答