6

我正在尝试找到一种在 perl webapp 中大写名称的解决方案(使用 perl v5.10.1)。我最初想使用 Lingua::EN::NameCase,但我发现重音字符存在一些问题。

我需要能够处理来自各种欧洲语言(爱尔兰语、法语、德语)的重音字符。

我在网上看到一些迹象表明 Lingua::EN::NameCase 应该适用于我的用例。例如,这个关于 perlmonks 的页面:http ://www.perlmonks.org/?node_id=889135

这是我基于上述链接的测试代码:

#!/usr/bin/perl

use strict;
use warnings;
use Lingua::EN::NameCase;
use locale;
use POSIX qw(locale_h);

my $locale = 'en_FR.utf8';

setlocale( LC_CTYPE, $locale );

binmode DATA,   ':encoding(UTF-8)';
binmode STDOUT, ':encoding(UTF-8)';

while (my $original_name = <DATA>) {
    chomp $original_name;
    my $normalized_name = nc($original_name);
    printf "%30s L::EN::NC %30s UCFIRST %30s\n", $original_name, $normalized_name, xlc($original_name);
}

sub xlc {
    my $str = shift;
    $_ = lc( $str );
    return join q{} => ( map { ucfirst(lc($_)) } ( $str =~ m/(\W+|\w+)/g ) );
};

__DATA__
ÉTIENNE DE LA BOÉTIE
ÉMILIE DU CHÂTELET
HÉLÈNE CIXOUS
Seán Ó Hannracháín
Máire Ó hÓgartaigh

产生下面的输出。L::EN::NC 和自定义 ucfirst(lc()) 解决方案都会产生不正确的结果(注意每个重音字符后面的大写字母)。这似乎是因为 perl 正则表达式在每个重音字符之前/之后匹配“单词边界”。我本来希望单词边界仅在空格字符和非空格字符之间匹配。

有人可以提出解决方案吗?

谢谢,

布赖恩。

  ÉTIENNE DE LA BOÉTIE L::EN::NC           éTienne de la BoéTie UCFIRST           ÉTienne De La BoÉTie
    ÉMILIE DU CHÂTELET L::EN::NC             éMilie du ChâTelet UCFIRST             ÉMilie Du ChÂTelet
         HÉLÈNE CIXOUS L::EN::NC                  HéLèNe Cixous UCFIRST                  HÉLÈNe Cixous
    Seán Ó Hannracháín L::EN::NC             SeáN ó HannracháíN UCFIRST             SeÁN ó HannrachÁíN
    Máire Ó hÓgartaigh L::EN::NC             MáIre ó HóGartaigh UCFIRST             MÁIre ó HÓGartaigh
4

4 回答 4

1

Perl 5.10 已经过时了;如果可以的话,你应该更新它。

接下来,您将找到我用于类似情况的版本。(在 perl 5.14.2 中测试)

#!/usr/bin/perl

use strict;
use warnings;
use utf8::all;

while (<DATA>) { chomp;
    printf "%30s ==> %30s\n", $_, xlc($_);
}

sub xlc { my $str = shift;
    $str =~ s/(\w+)/ucfirst(lc($1))/ge;
    $str =~ s/( L[ea]s?
               | Von
               | D[aeou]s?
               )\b
              /lc($1)/xge;
    return $str;
};

__DATA__
ÉTIENNE DE LA BOÉTIE
ÉMILIE DU CHÂTELET
HÉLÈNE CIXOUS
Seán Ó Hannracháín
Máire Ó hÓgartaigh
于 2014-02-18T19:41:57.630 回答
0

实际上你只需要 utf8 编译指示。

use utf8;
binmode STDOUT, ':utf8'; 

while (my $name = <DATA>) {
    $name =~ s/(\w+)/ucfirst lc $1/eg;
    print $name;
}

__DATA__
ÉTIENNE DE LA BOÉTIE
ÉMILIE DU CHÂTELET
HÉLÈNE CIXOUS
Seán Ó Hannracháín
Máire Ó hÓgartaigh

我得到:

Étienne De La Boétie
Émilie Du Châtelet
Hélène Cixous
Seán Ó Hannracháín
Máire Ó Hógartaigh
于 2014-06-10T22:44:56.233 回答
0

如果您的数据是 UTF8 格式,您应该将其解码为 perl 的内部编码:

    utf8::decode($original_name);
    my $normalized_name = nc($original_name);
    printf "%30s L::EN::NC %30s UCFIRST %30s\n", $original_name, $normalized_name, xlc($original_name);
于 2013-10-16T14:42:57.820 回答
0

好的,我刚刚让你的脚本工作。这是我得到的输出:

      ÉTIENNE DE LA BOÉTIE L::EN::NC           Étienne de la Boétie UCFIRST           Étienne De La Boétie
        ÉMILIE DU CHÂTELET L::EN::NC             Émilie du Châtelet UCFIRST             Émilie Du Châtelet
             HÉLÈNE CIXOUS L::EN::NC                  Hélène Cixous UCFIRST                  Hélène Cixous
        Seán Ó Hannracháín L::EN::NC             Seán Ó Hannracháín UCFIRST             Seán Ó Hannracháín
        Máire Ó hÓgartaigh L::EN::NC             Máire Ó Hógartaigh UCFIRST             Máire Ó Hógartaigh

我不得不改变两件事:

  1. 我注释掉了 binmode 调用,因为无论我的 emacs 在我的系统上使用什么编码都不需要它们。你的旅费可能会改变。如果您弄错了,您将看到有关未映射到 Unicode 或宽字符的字符的警告。

  2. 我改变了本地。你告诉它使用法国的英语语言环境。我不确定这是一个有效的语言环境。我选择了一个实际使用重音字符的本地人。

不幸的是,语言环境名称没有标准化,但以下语言环境对我有用:

my $locale = 'fr_FR.utf-8';

特别是,如果没有连字符,它就不起作用。

于 2014-04-15T01:52:44.513 回答