ソートがɛ= eと言うのはなぜですか?


25

ɛ(「ラテン語イプシロン」)は、特定のアフリカの言語で使用される文字で、通常は英語の「bed」で母音を表します。ユニコードでは、U + 025Bとしてエンコードされており、毎日とはまったく異なりeます。

ただし、sort次の場合:

eb
ed
ɛa
ɛc

sort考慮しɛe同等と思われる:

ɛa
eb
ɛc
ed

何が起きてる?また、目的のために作成ɛしてe区別する方法はありsortますか?


21
並べ替えルールは「照合」と呼ばれます。これがグーグル検索に役立つ場合
BlueRaja-Danny Pflughoeft

1
テキストファイル内に特定の数のea混合ɛa文字を入れて並べ替えます。常にea前にソートされることがわかりɛaます。したがって、それらは同等とは見なされません。
バクリウ

明らかなポイントかもしれませんが、まだ明示的に示唆されているのを見たことはありません。$(certain_african_language)で単語を並べ替える場合、行うべき自然なことはロケールを$(certain_african_language)に設定することです。
フェデリコポロニ

@FedericoPoloni非常に良い点!残念ながら、この言語用に作成されたロケールを見つけることができませんでした。
ドラコニス

1
@GermánBouzasこれは、特に「ラテン語イプシロン」、ラテン語のアルファベットに合うように設計された形式です。見た目はほとんど同じですが、ラテン語のイプシロンはU + 025Bで、ギリシャ語のイプシロンはU + 03B5です。
ドラコニス

回答:


67

いいえ、それは同等とは見なされず、単に同じ主要重量を持ちます。そのため、最初の近似では、それらは同じようにソートされます。

GNUシステム(ここではglibc 2.27)で/ usr / share / i18n / locales / iso14651_t1_common(ほとんどのロケールのベースとして使用)を見ると、次のように表示されます。

<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U025B> <e>;<PCL>;<MIN>;IGNORE # 287 ɛ
<U0045> <e>;<BAS>;<CAP>;IGNORE # 577 E

eɛおよびE同じプライマリウェイトeE同じセカンダリウェイトを持ち、3番目のウェイトだけがそれらを区別します。

文字列を比較するときsortstrcoll()標準のlibc関数は文字列を比較するために使用されます)、すべての文字のプライマリウェイトを比較することから始まり、文字列がプライマリウェイトと等しい場合(他のウェイトと同様)、2番目のウェイトのみに進みます。

これが、最初の近似のソート順で大文字小文字が無視されるように見える方法です。Abとの間aaで並べ替えますacが、言語規則Abab応じて前後に並べ替えることができます(一部の言語では、<MIN><CAP>に英国英語、<CAP><MIN>にエストニア語などがあります)。

場合はe、同じソート順を持っていたとしてɛprintf '%s\n' e ɛ | sort -u一つだけの行が返されます。しかしとして<BAS>のソートの前に<PCL>e一人でのソートの前に ɛeɛe後にソートしEEEていても(二重に)EEEソートが後にeee(そのために私たちは第三体重まで行く必要があります)。

glibc 2.27を使用しているシステムで次のコマンドを実行すると:

sed -n 's/\(.*;[^[:blank:]]*\).*/\1/p' /usr/share/i18n/locales/iso14651_t1_common |
  sort -k2 | uniq -Df1

まったく同じ4つの重みで定義された文字がかなりあることに気付くでしょう。特に、ourの重みは次と同じです。

<U01DD> <e>;<PCL>;<MIN>;IGNORE
<U0259> <e>;<PCL>;<MIN>;IGNORE
<U025B> <e>;<PCL>;<MIN>;IGNORE

そして確かに:

$ printf '%s\n' $'\u01DD' $'\u0259' $'\u025B' | sort -u
ǝ
$ expr ɛ = ǝ
1

これは、GNU libcロケールのバグと見なすことができます。他のほとんどのシステムでは、ロケールはすべての異なる文字が最終的に異なるソート順序を持つようにします。ソート順を持ち、同じ仕分けまで終わらない文字の数千人があるとしてGNUロケールで、それは破壊のように(あらゆる種類の問題を引き起こし、さらに悪くなりcommjoinls非決定論注文を持つか、グロブ... )、したがって、これらの問題を回避するため使用LC_ALL=Cすることをお勧めします

@ninjaljのコメントで指摘されているように、2018年8月にリリースされたglibc 2.28にはAFAICSがありますが、同じ並べ替え順序で定義されたいくつかの文字または照合要素がまだありますが、その面でいくつかの改善が行われました。glibc 2.28を使用し、en_GB.UTF-8ロケールのUbuntu 18.10で。

$ expr $'L\ub7' = $'L\u387'
1

(なぜU + 00B7は、L/ l?! と組み合わせた場合にのみU + 0387と同等と見なされますか)。

そして:

$ perl -lC -e 'for($i=0; $i<0x110000; $i++) {$i = 0xe000 if $i == 0xd800; print chr($i)}' | sort > all-chars-sorted
$ uniq -d all-chars-sorted | wc -l
4
$ uniq -D all-chars-sorted | wc -l
1061355

(100万文字以上(Unicode範囲の95%、2.27の98%から)は、ソート順が定義されていないため、他の文字と同じようにソートされます)。

こちらもご覧ください:


3
これはまさに私が探していたものです!完全を<PCL>期すために、何の略ですか?その他は、Capital、Miniscule、Basicですか?
ドラコ連合

3
@Draconis、照合シンボル<PCL>#16 PARTICULIER /独特
ステファンChazelas

実際、ファイルに束ねeaɛa混ぜると、sortすべてeaのがの前にソートされることがわかりますɛa
バクリウ

2
glibc 2.28以降、コードポイントは4レベルの重みのフォールバックとして使用する必要があります。sourceware.org / git
…を

1
@cat、申し訳ありませんが、私はstrcoll()、編集を参照してください。
ステファンシャゼル

15

男の並べ替え:

   ***  WARNING  ***  The locale specified by the environment affects sort
   order.  Set LC_ALL=C to get the traditional sort order that uses native
   byte values.

だから、試してください: LC_ALL=C sort file.txt


1
動作します!しかし、なぜデフォルトのロケールでは、これらの完全に分離されたコードポイントが同じであると見なされますか?これがなぜ起こるのか興味があります。
ドラコニス

@Draconis「デフォルトのロケール」とは何ですか?
カミルマシオロウスキ

@KamilMaciorowski環境変数の空の値。対応するロケールがわかりません。
ドラコニス

3
@Draconis if LC_ALLが空のsort場合、他のLC_*変数LANGまたはいくつかの構成ファイルを使用できます。
-NieDzejkob

1
LC_COLLATE文字列ソート固有のもので、LANG一般的なものです。
ShadowRanger

8

文字Theはeとは異なりますが、一部のロケールでは、照合時にこれらの記号を近くに集めることができます。この理由は言語固有ですが、歴史的または政治的な背景もあります。たとえば、ほとんどの人は、おそらくユーロ通貨が辞書でヨーロッパに近づくと予想しています。

とにかく、現在使用している照合を実行するlocaleにはlocale -a、システムで使用可能なロケールのリストを表示し、C1回の並べ替えの実行に対して照合順序を変更しますLC_COLLATE=C sort file。最後に、異なるロケールがファイルをソートする方法を確認してみてください

for loc in $(locale -a)
    do echo ____"${loc}"____
    LC_COLLATE="$loc" sort file
done

結果をいくつかのグレーピングツールにパイプして、ニーズに合ったロケールを選択します。


これは素晴らしい説明ですが、シンボルは互いに近いだけでなく、同一と見なされるようです。
ドラコニス

1
いいえ、それらは同一とは見なされません。eaファイルに単純な行を追加すると、出力と出力のsort -u両方が得られます。最善の戦略と照合順序は、回避()です。そうしないと、多くのいことが起こります(例:in は一致しますが、一致しません)。eaɛaexport LC_COLLATE=C/tmp/[a-z]bash/tmp/a/tmp/A/tmp/Z
モスビー

@mosvy Huh、おもしろい…それらは順序付けの目的では同じと見なされますが、一意性の目的ではありませんか?
ドラコニス

それらは同じとは見なされません。ここで説明を参照してください。
モスビー

1
@ninjalj、これはglibc fnmatch()およびregexpの範囲で修正されますが、bashを使用して範囲を単独で実装するようなものではありませんstrcoll()。ksh93は、その範囲の実装strcoll()で範囲の終わりの大文字と小文字の区別を使用およびチェックし、両端が小文字の場合にのみ小文字に一致するため、問題は発生しませんでした。zsh範囲はstrcoll()ではなくコードポイントに基づいて行われるため、問題はありません。
ステファンシャゼラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.