2016-09-02 15 views
0

ここでは、ユニコード文字列の大文字の前後にかっこを追加する単純な代入があります。あなたが見ることができるように、結果はかなり醜いです:論理ユニコード文字のPerl正規表現置換

~$ echo "Whatéver 5" | perl -ape "s/(\p{Upper})/(\1)/g" 
(W)hat(�)�ver 5 

私の理解では、正規表現は無意味な文字に私の「E」を分割し、「コードポイント」の代わりに「論理的な文字」、上で動作することです。正規表現を論理的なUnicode文字で一度に動作させる方法はありますか?

おかげで、それはあなたがデフォルトのエンコーディングを設定することができますプログラム内の別々の文字

としてのエンコードの各バイトを処理されるようにするには、UTF-8の入力を期待するPerlを告げていない

+0

入力と出力にUTF8 PerlIOレイヤがありません。期待どおりに動作します: 'echo -n"Whatéver5 "| perl -Mutf8 -CSDA -pe /(\ p {Upper})/(\ 1)/ g "'となる。参照:[大文字の正規表現の正規表現は "Ó"と一致しませんか?](http://stackoverflow.com/questions/10891643/regex-for-uppercase-unicode-does-not-match-%C3%93) –

答えて

1

で正しい$1\1を交換しましたPerlプログラムへの入力は内部的にUnicodeに変換されていません(まだUTF-8バイトの文字列です) は、Perlの文字列に入力を変換するオプション-CI使用して標準入力ストリームにUTF-8層を追加するには:あなたがあれば、

E9 

しかし

$ echo -n "é" | perl -CI -ne 'printf "%vX\n", $_' 

出力は今をまた、文字を標準出力に戻してみてください éではなく、ユニコード交換文字を端末から取得します。文字0xE9がUnicodeですが、端末がUTF-8を期待する、と0xE9が有効なUTF-8ではありませんので、これは次のとおりです。

$ echo -n "é" | perl -CI -nE 'printf "$_: %vX\n", $_, $_' 
�: E9 

正しい出力を取得するには、標準のUFT-8エンコーディング層を追加することができますまた、出力ストリーム(-COフラグを使用):

$ echo -n "é" | perl -CIO -nE 'printf "$_: %vX\n", $_, $_' 
é: E9 

perlunicode

によれば、 "上部" は "大文字" の同義語であり、そして我々は肝炎ができeはP \ 書き込ま{大文字は}同等の\ P {上位}例えば

として、\ pは{大文字は} ユニコード "大文字" プロパティを使用して任意の1文字に一致し

バイト文字列に\p{Upper}を使用しようとすると、Perlからの警告は表示されません。 0xC00xDEの範囲のバイトも大文字のプロパティと一致します。 0xC30xA9(UTF-8で)ここで

$ echo "Whatéver 5" | perl -ape "s/(\p{Upper})/(\1)/g" 
(W)hat(�)�ver 5 

、手紙 éは2バイトで表され、 0xC3がUnicode Upperプロパティと一致します:これは、あなたが得た出力を説明し

perl -E 'for $i (0x80..0xFF) {$_=chr $i; printf "%x\n", $i if /\p{Upper}/}' 

試してみてください。

(W)hatéver 5 
:出力と

echo "Whatéver 5" | perl -CS -ape "s/(\p{Upper})/(\1)/g" 

あなたの問題を解決するには、(あなたが-CSを使用して-CI-COを組み合わせることができます)標準入力と標準出力にUTF-8エンコーディングの層を追加することです

2

コマンドラインでこの

use open ':std' => ':encoding(UTF-8)' 

のような3つの標準的なIOチャネルは、オプション-CSは同じことを行い、これはあなたのために働く必要があります。私は

$ echo -n "é" | perl -ne 'printf "%vX\n", $_' 

C3.A9 

を与え、不要な自動splitオプションを削除し、あなたの端末がUTF-8エンコーディングを使用すると仮定すると、置換文字列

echo "Whatéver 5" | perl -CS -pe "s/(\p{Upper})/($1)/g" 
2

他の回答で示されているように、PerlでUTF-8を有効にすることは、単なるプロセスです。構文と生の文字列にはuse utf8があります。その後、すべてのファイルハンドルがUTF-8であることを確認する必要があります。 @ARGVはどうですか? readdirglob``の出力は?

プログラムの半分をASCIIで動作させ、残りの半分をUTF-8で動作させることよりも悪いことはありません。レスキューにutf8::all

これをインストールすると、use utf8::allが追加され、UTF-8がすべてオンになります。誰かがそれを理解した、あなたはそれについて心配する必要はありません。

$ echo "Whatéver 5" | perl -ape "use utf8::all; s/(\p{Upper})/(\1)/g" 
(W)hatéver 5