【问题标题】:Extracting lowercased russian words from UTF8 text从 UTF8 文本中提取小写俄语单词
【发布时间】:2013-03-11 14:55:08
【问题描述】:

在 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;
}

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

请问有没有人知道怎么回事?

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

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

【问题讨论】:

  • \p{Cyrillic}\p{Lowercase_Letter}代替范围怎么样?
  • 是的,我已经阅读了有关 \p{Cyrillic} 的信息 - 但只想提取完全小写的单词(即不是我的示例文本中的第一个单词,也不是第五个单词)。我不知道如何在这里做?

标签: perl unicode utf-8 text-extraction utf


【解决方案1】:

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

#!/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 utf8lc()会知道to小写字母。

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

【讨论】:

  • 嗯,__DATA__ 效果很好,但不是单独的 .txt 文件?我应该binmode(ARGV, ':utf8') 或类似的东西吗?
【解决方案2】:

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

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

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

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

\b(((?=\p{Cyrillic})\p{Lowercase_Letter}){3,})\b

【讨论】:

  • 很遗憾不起作用 - 没有打印任何内容。无论是在 Windows 上,还是在 Linux 上(在 Vim 中编辑 UTF8 文本都可以)。
  • 抱歉\b(((?=\p{Cyrillic})\p{Lowercase_Letter}){3,})\b 无法使用utf8::decode($_); 的事件:一次又一次地打印相同的俄语单词。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-10
  • 1970-01-01
  • 2010-10-23
  • 1970-01-01
相关资源
最近更新 更多