2016-02-13 4 views
6

特定の発音区別記号を持つ文字の正規表現を指定する方法はありますか?たとえば重大なアクセントを考えてみましょう。かなり面倒だ正規表現で特定の発音区別符を持つ文字

/[àầằèềḕìǹòồṑùǜừẁỳ]/i 

を:これを行うには長い道のりには、それらのうち、文字クラスを作成し、その後、Wikipedia page on the grave accentに行くことが示した文字のすべてをコピーすることです。私は\p{hasGraveAccent}のようなUnicodeプロパティを望んでいましたが、私はそのようなものを見つけることはできません。解決策を探すには、文字の一致に気をつけようとしている人からの質問だけが出てくる。発音の区別は無視されている。

+0

それが結合文字の場合は、[Unicodeコードポイントのリストを生成する]ことで可能かもしれません(http://stackoverflow.com/questions/17051732/algorithm-to-check-for-combining-characters-in-unicode )。 – kba

+0

一文字の文字クラスを信頼できず動作させないようにする。これは、文字列NFC(正規化フォーム構成)に一致する事前合成された文字に対してのみ機能します。 2つ以上の発音区別符を持つほとんどの文字には、事前合成された文字はありません。私。それらは複数のコードポイント(Unicodeスピーチでは文字)で構成されています。それをコピーして文字クラスに貼り付けると、区別記号​​は引き続き1文字になり、ターゲット文字列内の同じ発音区別記号に一致します。 –

答えて

0

これはちょっと難しい質問ですが、可能です。まず、ユニコード文字列を4つの形式のいずれかに正規化する必要があります。正規化に関する情報はhereであり、正規化された文字例のマップはhereであり、正規化された文字の良いグラフはhereです。基本的に、正規化すると、発音区別記号を扱うときに、すべての文字が同じ形式になるようにします。 Golangはこれを大いにサポートしており、ほとんどすべての言語にはこれを行うためのライブラリが含まれています。

私の例では、文字列を「正規化フォームD」(NFD)とutf32に変換するので、すべてのユニコード文字は4バイトのコードポイントになります。

墓地アクセントのすべての二重引用符は、文字の隣に0x0300を持っています。だから、....\x00\x00\x03\x00のasciiモード(Unicodeモードではない)で正規表現検索を行うことができます。そこから、あなたが使用しているエンコーディングに応じて異なる方法で行うことができるruneの場所を抽出する必要があります。

したがって、4の部門に着陸すれば、その有効な文字がわかります。

これ以外に、これを行うための公式のperl文字グループはありません。

例として、Perlコード:

use Encode; 
use Unicode::Normalize; 

$StartUTF8='xàaâèaê'; 
$PerlEncoded=decode('utf8', $StartUTF8); 
$PerlNormalized=NFD($PerlEncoded); 
$UTF32Normalized=encode('utf32', $PerlNormalized); 

while($UTF32Normalized =~ /(....\x00\x00\x03\x00)/gs) { 
    $Pos=pos($UTF32Normalized)-8; 
    if($Pos%4==0) { 
     print("$Pos\n"); 
    } 
} 

しかし、この時点で、あなたにもちょうど文字の上にループのためにやっているかもしれません: -

\私はまた、位置を必要とせずにマッチングを試みました// cを使ってテストしますが、なんらかの理由で動作しません。

/^(?:....)*?(....\x00\x00\x03\x00)/gcs

+0

UTF32に変換するポイントはありません(また、結果がUTF-32LEであると仮定している場合は、偶然に残すのではなく変換する必要があります)。また、グリフに2つ以上の発音区別符が含まれていると、アクセント記号がベース文字の直後に続くという前提が正しくない可能性があります。 – rici

+0

確かに。それはかなり実りのない研究とテストでした – Dakusan

1

いくつかの制限があります。組み合わせて編集領域内の文字が正しく表示されますが、stackoverflowのは、彼らが間違って区切りレンダリング:

#!perl 

use strict; 
use warnings; 

use Encode; 
use Unicode::Normalize; 
use charnames qw(); 
use utf8; # source is utf-8 

binmode(STDOUT, ":utf8"); # print in utf-8 

my $utf8_string = 'xàaâèaêòͤ'; 

my $nfd_string = NFD($utf8_string); # decompose 

my @chars_with_grave = $nfd_string =~ 
    m/ 
    (
     \p{L}   # one letter 
     \p{M}*   # 0 or more marks 
     \N{COMBINING GRAVE ACCENT} 
     \p{M}*   # 0 or more marks 
    ) 
    /xmsg; 

print join(', ',@chars_with_grave), "\n"; 

これは

$ perl utf_match_grave.pl 
à, è, òͤ 

NOTEを印刷します。

基本文字として文字が必要です。他のベース文字の正規表現を変更します。マーク\p{M}は、正確にはあなたが望むものではないかもしれないが、改善すべきである。

関連する問題