2013-10-16 30 views
6

perl webapp(perl v5.10.1を使用)で名前を大文字にするソリューションを探しています。もともと私はLingua :: EN :: NameCaseを使うと思っていましたが、アクセント付きの文字にはいくつかの問題があります。アクセント付き文字を含む文字列を大文字にする

さまざまなヨーロッパ言語(アイルランド語、フランス語、ドイツ語)のアクセント付き文字に対応できる必要があります。

私はLingua :: EN :: NameCaseが私のusecaseのために動作するはずのいくつかの兆候を見ました。例えば、perlmonks上のこのページ:

#!/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 

以下の出力を生成します。http://www.perlmonks.org/?node_id=889135

ここでは、上記のリンクに基づいて、私のテストコードがあります。 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 
+3

参照[Perlで大文字アクセント付き文字](http://stackoverflow.com/questions/13261522/uppercase-accented-characters-in-perl) – hwnd

+0

リンクしているページhwndは面白いですが、utf8フラグ*は '$ original_name'に設定されています:すべてが正しくデコードされています。 – amon

+0

確かに。大文字小文字の問題はありません。 uc()とlc()は、私がそれらに送るどの文字列でもうまく動作するようです。問題はL :: EN :: NCがその単語の最初の文字を大文字にするために単語の先頭を正しく識別できないように見えることです。 L :: EN :: NCに関連する正規表現は単語境界を識別するために '\ b 'を使用する' {\ b(\ w)} {\ u $ 1} gox; 'です。私にとっては、 '\ b'はアクセント付きの文字とアクセントのない文字の間の変化を単語の境界として識別しているようです。 –

答えて

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); 
+0

を参照してください。ありがとうBohdan。私のデータは確かにUTF8です - utf8 :: is_utf8($ original_name)はtrueを返します。しかし、utf8 :: decode()は私に望ましい出力を与えません。しかし、それは出力を変更します。だから、L :: EN :: NCの代わりに私の元の例で "éTiennede laBoéTie"を与えて、 "ÉTiennede laBoÉTie"を与えます。資本金は変わってきましたが、私はまだ弦の真ん中に偽の首都があります。 –

1

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 
+0

ちょうど私たちがほぼ同じ回答をしたことに気づいた。あなたが最初です。だからここに私のupvote :) – Pierre

0

OK、私はあなたのスクリプトを動作させました。ここで私が得た出力です:私は彼らが私のシステムで使用され、私のemacsをコードするものは何でもして必要とされていなかったので、binmodeを呼び出しをコメントアウト

  1.  É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 
    

    私は二つのことを変更しなければなりませんでした。あなたのマイレージは異なる場合があります。間違ってしまうと、Unicodeやワイド文字にマップされない文字に関する警告が表示されます。

  2. ローカルを変更しました。あなたはフランスで英語圏のロケールを使用するように指示していました。私はそれが有効なロケールであるかどうかはわかりません。実際にアクセント付きの文字を使用するローカルを選んだ。

残念ながら、ロケール名は、標準化されていないが、次のロケールが私の仕事:特に、それはハイフンなしで動作しませんでした

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

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 
関連する問題