我正在尝试找到一个在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
答案 0 :(得分: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
答案 1 :(得分: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);
答案 2 :(得分: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
我不得不改变两件事:
我注释掉了binmode调用,因为我的emacs在我的系统上使用的编码不需要它们。你的旅费可能会改变。如果你弄错了,你会看到关于没有映射到Unicode或宽字符的字符的警告。
我改变了本地。你告诉它在法国使用说英语的语言环境。我不确定这是一个有效的语言环境。我选了一个实际上使用重音字符的本地。
不幸的是,语言环境名称没有标准化,但以下语言环境对我有用:
my $locale = 'fr_FR.utf-8';
特别是,如果没有连字符,它就无效。
答案 3 :(得分:0)
其实你只需要utf8 pragma。
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