一部のUnicode文字を含む「uniq」または「sort -u」行はどこに行きましたか?

一部のUnicode文字を含む「uniq」または「sort -u」行はどこに行きましたか?

以下のコードスニペットでは何が起こっていますか?期待した結果が得られませんでした。

私はこれがバグだと思いますが、2つの異なるプログラム(uniqとsort)で発生するので、これが何か関連していると思われます...まあ、何が起こっているのかわかりません...したがって問題が発生します。

最初の3つ(4つのうち)の例は機能しますが、4番目の例は失敗します!

私はすべてのキャラクターが同じように行動したいと思います。
つまり。 (入力3行のうち)2行を印刷します...しかし、4番目の場合は1行だけを取得します(合計の場合sort -uuniq。 2つの同じ行が消えます。

ビューを簡潔に保つために、出力 '\ n'を空白に変換しました。

私はそれを使用していますユニークそしてタイプ(GNU coreutils)7.4以降... Ubuntu 10.04.3 LTSデスクトップで動作します。

スクリプト:

{
  locale -k LC_COLLATE
  echo
  for c1 in x 〼 ;do 
    for c2 in z 〇 ;do 
      echo -n "asis   : "; echo -e "$c1\n$c2\n$c2"          |tr '\n' ' ';echo
      echo -n "uniq   : "; echo -e "$c1\n$c2\n$c2" |uniq    |tr '\n' ' ';echo
      echo -n "sort -u: "; echo -e "$c1\n$c2\n$c2" |sort -u |tr '\n' ' ';echo
      echo
    done
    echo
  done
}

出力:

collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2081
collate-codeset="UTF-8"

asis   : x z z 
uniq   : x z 
sort -u: x z 

asis   : x 〇 〇 
uniq   : x 〇 
sort -u: 〇 x 


asis   : 〼 z z 
uniq   : 〼 z 
sort -u: 〼 z 

asis   : 〼 〇 〇 
uniq   : 〼 
sort -u: 〼 

# In the last example (of 4) where did the '〇' go? .. U+3007 IDEOGRAPHIC NUMBER ZERO
#

答え1

ショートバージョン:コマンドラインユーティリティでは、照合順序は実際には機能しません。

より長いバージョン:2つの文字列を比較する基本関数は次のとおりです。strcoll。説明はあまり役に立ちませんが、概念的にこれを行う方法は、2つの文字列を標準形式に変換してから2つの標準形式を比較することです。機能strxfrmこの正式な形式が構成されます。

いくつかの文字列の標準形式を見てみましょう(Debian squeezeでGNU libcを使用)。

$ export LC_ALL=en_US.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' b a A à 〼 〇
b d010801020
a c010801020
A c010801090
à 101010102c6b
〼 101010102c6b102c6b102c6b
〇 101010102c6b102c6b102c6b

ご覧のように〼と〼は同じ標準形を持っています。私の考えでは、その文字がen_US.UTF-8そのロケールの組み合わせテーブルに記載されていないためです。ただし、日本語ロケールでは表示されます。

$ export LC_ALL=ja_JP.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' 〼 〇 
〼 303030
〇 3c9b

ロケールデータ(Debian squeezeの)ソースコードは/usr/share/i18n/locales/en_USincludeにあります。このファイルには、またはエントリが/usr/share/i18n/locales/iso14651_t1_commonなく、私が見つけることができる範囲には含まれていません。U3007U303C

私は慣れていないソートルール設定ルールしかし、私が理解したところによると、関連表現は次のようになります。

UNDEFINEDシンボルは、明示的に指定されていないか省略記号で指定されていないすべてのエンコードされた文字セット値を含むと解釈されます。 (...)未定義のシンボルが指定されておらず、現在エンコードされている文字セットにこのセクションに指定されていない文字が含まれている場合、ユーティリティは警告メッセージを発行し、その文字を文字ソート順序の末尾に配置する必要があります。

Glibcは指定されていない文字を無視するようです。 POSIX仕様の理解に欠陥があるのか​​、Glibcロケール定義に欠けている部分があるのか​​、Glibcロケールコンパイラにバグがあるのか​​はわかりません。

答え2

Unicode文字列を「安全に」使用するには、sort次の点を見てくださいmsort

[...] Msortは、キーフィールドの選択、より多くの比較タイプ、異なるキーから異なるロケールの照合順序を使用する機能、非西欧数値システムの数値を処理する機能、およびその他のさまざまなオプションの面で不足しています。より大きな柔軟性を提供します。 GNUソートとBSDソート。 msortはUnicodeを理解していますが、GNUソートとBSDソートは理解していません。 [...]

http://www.billposer.org/Software/msort.html

関連情報