7

なぜこれは aUではなく a を出力するのÜですか?

#!/usr/bin/env perl
use warnings;
use 5.014;
use utf8;
binmode STDOUT, ':utf8';
use charnames qw(:full);

my $string = "\N{LATIN CAPITAL LETTER U}\N{COMBINING DIAERESIS}";

while ( $string =~ /(\X)/g ) {
        say $1;
}

# Output: U
4

4 に答える 4

8

あなたのコードは正しいです。

これらのことを数字でプレイする必要があります。「端末」が表示するものを信用しないでください。おそらくorを使用しuniquote programを介してパイプし、実際に何をしているかを確認します。-x-v

目は欺き、プログラムはさらに悪化します。あなたの端末プログラムはバグが多いので、嘘をついています。正規化は重要ではありません。

$ perl -CS -Mutf8 -MUnicode::Normalize -E 'say "crème brûlée"'
crème brûlée
$ perl -CS -Mutf8 -MUnicode::Normalize -E 'say "crème brûlée"' | uniquote -x
cr\x{E8}me br\x{FB}l\x{E9}e
$ perl -CS -Mutf8 -MUnicode::Normalize -E 'say NFD "crème brûlée"' 
crème brûlée
$ perl -CS -Mutf8 -MUnicode::Normalize -E 'say NFD "crème brûlée"' | uniquote -x
cre\x{300}me bru\x{302}le\x{301}e

$ perl -CS -Mutf8 -MUnicode::Normalize -E 'say NFC scalar reverse NFD "crème brûlée"' 
éel̂urb em̀erc
$ perl -CS -Mutf8 -MUnicode::Normalize -E 'say NFC scalar reverse NFD "crème brûlée")' | uniquote -x
\x{E9}el\x{302}urb em\x{300}erc
$ perl -CS -Mutf8 -MUnicode::Normalize -E 'say scalar reverse NFD "crème brûlée"'
éel̂urb em̀erc
$ perl -CS -Mutf8 -MUnicode::Normalize -E 'say scalar reverse NFD "crème brûlée"' | uniquote -x
e\x{301}el\x{302}urb em\x{300}erc
于 2012-02-24T12:02:25.760 に答える
3

これは私にとってはうまくいきますが、5.012ubuntu に古いバージョンの perl があります。あなたのスクリプトへの私の唯一の変更は次のとおりです。use 5.012;

$ perl so.pl 
Ü
于 2012-02-24T10:38:51.797 に答える
1

1)どうやら、お使いの端末は外字を表示できないようです。私の端末では、次のように出力されます。

2) \X思ったように動かない。一緒に行くキャラクターを選択するだけです。string を使用する"fu\N{COMBINING DIAERESIS}r"と、プログラムは次のように表示します。

f
u¨
r

分音記号が単独ではなく、対応する文字とともに印刷されることに注意してください。

3)関連するすべての文字を 1 つに結合するには、モジュールUnicode::Normalizeを使用します。

use Unicode::Normalize;

my $string = "fu\N{COMBINING DIAERESIS}r";
$string = NFC($string);

while ( $string =~ /(\X)/g ) {
    say $1;
}

以下が表示されます。

f
ü
r
于 2012-02-24T10:51:22.023 に答える
1

間違っているのは出力だと思いますか?確認は簡単です: ループ コードを次のように置き換えます。

my $counter;
while ( $string =~ /(\X)/g ) {
  say ++$counter, ': ', $1;
}

...そして、正規表現が何回一致するか調べます。私の推測では、まだ一度しか一致しません。

または、次のコードを使用できます。

use Encode;
sub codepoint_hex {
    sprintf "%04x", ord Encode::decode("UTF-8", shift);
}

...そして、 while ループ内でプレーンな $1 の代わりに codepoint_hex ($1) を出力します。

于 2012-02-24T10:49:40.217 に答える