2012-03-15 8 views
3

なぜPerlの正規表現で "\、"、 "?、?、ç、ç、ö、ü"などのUnicode単語の文字は一致しませんか?Perlの正規表現で " w"のUnicode単語の文字(たとえば、 "ğ、İ、ç、ö、ü")が一致しないのはなぜですか?

正規表現m{\w+}gにこれらの文字を含めることを試みました。しかし、それは "ğ、İ、ş、ç、ö、ü"と一致しません。

どうすればこの作品を作成できますか?

use strict; 
use warnings; 
use v5.12; 
use utf8; 

open(MYINPUTFILE, "< $ARGV[0]"); 

my @strings; 
my $delimiter; 
my $extensions; 
my $id; 

while(<MYINPUTFILE>) 
{ 
    my($line) = $_; 
    chomp($line); 
    print $line."\n"; 
    unshift(@strings,$line =~ /\w+/g); 
    $delimiter = /[._\s]/; 
    $extensions = /pdf$|doc$|docx$/; 
    $id = /^200|^201/; 
} 

foreach(@strings){ 
    print $_."\n"; 
} 

入力ファイルのようです:

Çidem_Şener
HüsnüTağlip
...

出力は以下のようになります:

コードで
H� 

sn� 

Ta� 

lip 

� 

idem_� 

ener 

、I tr yファイルを読み込み、配列内の各文字列を取得します。 (デリミタは_または.または\sです)。

+0

関連しているが*ありません*重複:http://stackoverflow.com/questions/5555613/does-w-match-all-alphanumeric-characters-defined-in-the -unicode-standard、http://stackoverflow.com/questions/1796573/regex-word-breaker-in-unicode –

+0

あなたは 'open MYINPUTFILE、 '<:encoding(UTF-8)'、$ ARGV [0] ... '。さもなければあなたの入力は生の(オクテット)であり、期待どおりに解釈されません。 – mob

+0

認識できない文字\ xC3; C:/ Users/erogol/Documents/Aptana Studio 3 Workspace/Automata/file.txt行の第5列の近くにある - ここではMufeの後ろに - でマークされています。このエラーはユーザーには認識されず、 ... " – erogol

答えて

1

ユニコードは難題かもしれませんし、Perlには独自の特徴があります。 基本的に、Perlは、Unicodeに関するすべての入出力手段を取り巻くファイアウォールを設置しています。 I/OへのパスにエンコーディングがあるかどうかをPerlに伝えなければなりません。そうであれば、ルールは任意の入力に対してDECODE、および/または任意の出力に対してENCODEです。

デコードインは{encoding}のデータをPerlの内部表現に変換します。これはおそらくバイトとコードポイントの組み合わせです。

エンコードアウトは正反対です。

したがって、実際には2つの異なるエンコードに「デコード」および「エンコードアウト」することが可能です。あなたはそれが何であるかを伝えるだけです。エンコード/デコードは通常ファイルI/Oレイヤーを介して行われますが、Encodeモジュール(ディストリビューションの一部)を使用して、エンコード間を手動で前後に変換することができます。

perldocs on Unicodeは軽い読み込みではありません。

これは視覚化に役立つサンプルです(他にも多くの方法があります)。

use strict; 
use warnings; 
use Encode; 


# This is an internalized string with these UTF-8 codepoints 
# ---------------------------------------------- 
my $internal_string_1 = "\x{C7}\x{69}\x{64}\x{65}\x{6D}\x{5F}\x{15E}\x{65}\x{6E}\x{65}\x{72}\x{20}\x{48}\x{FC}\x{73}\x{6E}\x{FC}\x{20}\x{54}\x{61}\x{11F}\x{6C}\x{69}\x{70}"; 


# Open a temp file for writing as UTF-8. 
# Output to this file will be automatically encoded from Perl internal to UTF-8 octets. 
# Write the internal string. 
# Check the file with a UTF-8 editor. 
# ---------------------------------------------- 
open (my $out, '>:utf8', 'temp.txt') or die "can't open temp.txt for writing $!"; 
print $out $internal_string_1; 
close $out; 


# Open the temp file for readin as UTF-8. 
# All input from this file will be automatically decoded as UTF-8 octets to Perl internal. 
# Read/decode to a different internal string. 
# ---------------------------------------------- 
open (my $in, '<:utf8', 'temp.txt') or die "can't open temp.txt for reading $!"; 
$/ = undef; 
my $internal_string_2 = <$in>; 
close $in; 


# Change the binmode of STDOUT to UTF-8. 
# Output to STDOUT will now be automatically encoded from Perl internal to UTF-8 octets. 
# Capture STDOUT to a file then check with a UTF-8 editor. 
# ---------------------------------------------- 
binmode STDOUT, ':utf8'; 
print $internal_string_2, "\n\n"; 


# Use encode() to convert an internal string to UTF-8 octets 
# Format the UTF-8 octets to hex values 
# Print to STDOUT 
# ---------------------------------------------- 
my $octets = encode ("utf8", $internal_string_2); 
print "Encoded (out) string -> UTF-8 (octets):\n"; 
print " length = ".length($octets)."\n"; 
print " octets = $octets\n"; 
print " HEX val = "; 
for (split //, $octets) { 
    printf ("0x%X ", ord($_)); 
} 
print "\n\n"; 


# Use decode() to convert external UTF-8 octets to an internal string. 
# Format the internal string to codepoints (hex values). 
# Print to STDOUT. 
# ---------------------------------------------- 
my $internal_string_3 = decode ("utf8", $octets); 
print "Decoded (in) string <- UTF-8 (octets):\n"; 
print " length  = ".length($internal_string_3)."\n"; 
print " string  = $internal_string_3\n"; 
print " code points = "; 
for (split //, $internal_string_3) { 
    printf ("\\x{%X} ", ord($_)); 
} 

出力

Çidem_Şener Hüsnü Tağlip 

Encoded (out) string -> UTF-8 (octets): 
    length = 29 
    octets = Ãidem_Åener Hüsnü TaÄlip 
    HEX val = 0xC3 0x87 0x69 0x64 0x65 0x6D 0x5F 0xC5 0x9E 0x65 0x6E 0x65 0x72 0x20 0x48 0xC3 0xBC 0x73 0x6E 0xC3 0xBC 0x20 0x54 0x61 0xC4 0x9F 0x6C 0x69 0x70 

Decoded (in) string <- UTF-8 (octets): 
    length  = 24 
    string  = Çidem_Şener Hüsnü Tağlip 
    code points = \x{C7} \x{69} \x{64} \x{65} \x{6D} \x{5F} \x{15E} \x{65} \x{6E} \x{65} \x{72} \x{20} \x{48} \x{FC} \x{73} \x{6E} \x{FC} \x{20} \x{54} \x{61} \x{11F} \x{6C} \x{69} \x{70} 
3

PerlがデータをUTF-8として扱っていることを確認してください。

にマッチした出力

#!/usr/bin/perl 

use strict; 
use warnings; 
use v5.12; 
use utf8; # States that the Perl program itself is saved using utf8 encoding 

say "matched" if "ğİşçöü" =~ /^\w+$/; 

:それはスクリプト自体に埋め込まれている場合。 use utf8;行を削除しても、その行は削除されません。

+0

しかし、私は正確に "İşşöü"ではありません。それらは、他のすべての文字も含むユーザー名に含まれている可能性があります。 – erogol

+2

私はその答えを例のために使用しました。ポイントは、文字列の内部の "is UTF8"フラグがオンの場合に、 '\ w'があなたが望む文字と一致することです。 – Quentin

3

\w matches any of ğİşçöü just fine.

'ğİşçöü' =~ /\A \w+ \z/msx;  # true 

おそらく、ミスを犯し、Perlの文字にオクテットからの入力をデコードするのを忘れました。私はあなたの正規表現が文字レベルの代わりにバイトレベルで何かを調べると思っています。

http://p3rl.org/UNIhttp://training.perl.com/scripts/perlunicook.htmlを読んで、Perlでエンコードするトピックについて学んでください。


編集

問題は(私は、ファイルの内容ずに確実に伝えることができない)ここにありそうです:

open(MYINPUTFILE, "< $ARGV[0]"); 

は、おそらく、ファイルのエンコーディングを調べますそれはUTF-8またはWindows-1254です。それを書き直して、例えば:同様

open $in, '<:utf8', $ARGV[0]; 
open $in, '<:encoding(Windows-1254)', $ARGV[0]; 

、(あなたのプログラムの終わり近く)STDOUTにアウト印刷文字も同様にあるため、符号化の不足の壊れています。 ℞ 16: Declare STD{IN,OUT,ERR} to be in locale encodingは正しい方法を示しています。

関連する問題