単一文字リストのソート順の生成

単一文字リストのソート順の生成

場合によっては、個々の文字の組み合わせ順序を知る必要があります。通常、次のように表現されます。キャラクタークラス正規表現と同じです[b-d]。この文字クラスは次のように一致します。キャラクター与えられた範囲内で。

どの個人のb-d文字は範囲(または他の範囲)内の文字です。

また、C言語環境の組み合わせ順序は各ASCII文字のバイト値であることに注意してください。[ㅏ](33〜126の間の文字のみが表示されます):

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

文字範囲をASCII以上に拡張できますか?

しかし:

ソート順はどうなりますか?個々の文字他の地域では?

(すべてのロケールで)これらのソート順を表示する方法はありますか?

[ㅏ]ASCIIを使用するシステム(ほとんどのシステム)では、他のシステムではEBCDICまたは他のシステムを使用することもできます。

ベストアンサー1

これにはいくつかの側面があります。ロケールの文字セット内のすべての文字を一覧表示し、グラフィック文字(33〜126文字のASCII文字)を選択してソートする必要があります。

文字の並べ替え順序について話すのが妥当であるのか、それとも定義されたことがあるのか​​についての質問もあります。最後のポイントから始めます。

POSIX校正アルゴリズム

、または、シェルグローブまたは/、文字列比較演算子によって実装され使用されるC / POSIXソートアルゴリズム、およびより一般的にはPOSIXシステムでユーザーのロケールに基づいてテキストをソートするほとんどのツールについて話しているstrcoll()場合点に注意してください。sortlsawkexpr<>ひも

GNU システムの en_US.UTF-8 ロケールでは、é単一é文字で構成される文字列がソートされます。後ろに単一文字で構成される文字列eStéphaneソート済み今後 Stephanie。 cs_CZ.UTF-8ロケールでは、cとの間でソートしますが、間ではソートしません。bdchhi

対照アルゴリズムは、個々の文字ではなく文字列全体を考慮します。したがって、個別に比較するときに文字の順序を知ることは、その文字を含む文字列がどのように比較されるかを必ずしも知らせるわけではありません。

このアルゴリズムは、多くの実際の言語(辞書、電話帳など)などの文字列を比較するように設計されています。様々な文化の中で、ソートのすべての微妙さを扱うのはかなり単純です。集中治療室、より多くのアルゴリズムを実装しますが)ほとんどの場合は十分です。

このアルゴリズムでは要素の構成、これには文字だけでなく、韓国語のアルファベットやチェコ語のマルチパート文字などの文字の組み合わせも含まれます。chあるいは、一部のシステムでは、組み合わせの後に結合された予音(U + 0301)が複数の割り当てられた形式éで表示されます。e重量

そして完全な文字列比較は、最初の重みから最後の重みまで、順番に各重みを使用して実行されます。

たとえば、このen_US.UTF-8GNU ロケールでは、 、 、Eともに同じé基本重みを持ちます。そしてに分解eÉStéphaneStephanie

<S><t><é><p><h><a><n> <e>
<S><t><e><p><h><a><n> <i><e>

要素の組み合わせ(ここでは文字ごとに1つ)。

現時点では、n2つの文字列の対照要素は同じ主重みを持っていますが、の主i重みはesより大きいので、Stephanieソート後に二次Stéphane重みを考慮する必要はありません。

これでStephane、vsのStéphane場合は、基本重みを比較するときに等しくソートされるので、二次重みを考慮する必要があります。/usr/share/i18n/locales/iso14651_t1_commonen_US.UTF-8ロケールをそのまま使用してGNUシステムを調べると、次のことがわかります。

<BAS> # 15
[...]
<ACA> # 18
[...]
<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U00E9> <e>;<ACA>;<MIN>;IGNORE # 260 é

ラテンアルファベット文字の場合、発音区別符号を比較するために補助重みが使用される。デフォルトの文字(BAS)は急性アクセント()のある文字の前にありますACA。したがって、Stéphane順序はにあります。と比較するには、Stephane英語で大文字が小文字の後にある3番目の重みに達する必要があります(たとえば、エストニア語とは対照的に)。STÉPHANEStéphane

IGNOREまた、最初の比較では、主な重みが考慮または考慮されていない空白や句読点などの英数字以外の文字もあります(de factoこれらの文字はおよび間に並べられますが、空白が間に並べられるという意味ではありません)。defacedegreefg

$'STE\u0301HANE'vsでは、Stéphane一部のシステム(Solarisなど)は、最後の文字が(U + 00C9)文字であることをE\u0301除いて、同じ重みを持つ対照要素として扱いますが、他のシステムはそれを句読点として処理して結果を提供します。 。良いです(以前のものと同じです)。É\u0301$'STE\u0301HANE'Stephane

一つでもないみんな注文する

GNUシステムではU + 0301のソート順序も定義されていません。この場合、何千もの文字があります。。私は丸められた数字(U + 2460 ... U + 2473)を例として使用したいと思います。なぜなら、この数字は明らかにソート順を持つべきですが、そうではないからです。

$ touch ① ② ③ ④ ⑤
$ ls
④  ③  ⑤  ②  ①
$ ls | sort -u

実際には、他の文字と同じ重みを持つように定義されたいくつかの文字もあります(たとえば、 ƎここƏƐは順序はすべて同じです)。

sortしたがって、一部の実装で実行する場合を除いて、一部のロケールでは、ランダムな文字をソートすることは実際には不可能です。これは、POSIX 仕様の次のメジャーバージョンの要件になります。)、memcmp()同じ順序の文字に対して同様の比較を実行できます。

ロケール文字セットのすべてのグラフィック文字のリスト

ロケールごとに異なる文字セットを使用できます。

文字セットには3つの主なカテゴリがあります。 ASCIIやiso-8859-xなどのシングルバイト文字セット(各バイトは文字に対応)(一部は定義されていない場合があります)、文字が異なるバイト数でエンコードされているUTF-8、GB18030、BIG5、またはEUCJPなどステートフルバイト

最後のカテゴリは最近ロケールでほとんど使用されず、管理が難しいことが多いので、今は無視しても構いません。

C ロケールは本質的に単一バイト文字セットを持つことが保証されます。 EBCDICベースではないシステムで一般的に見られますが、必ずしもASCIIである必要はありません。

一部のスクリプト(英語で使用されるラテンスクリプトなど)は左から右に、他のスクリプトは右から左に書かれているため、これらの他のスクリプト(一部の文字セットでサポートされている)の文字は同じ行にあります。必ずしも良い考えではありません。

キャラクターの組み合わせも同様ですが、結局ランダムなキャラクターに組み合わせて合わされることになります。

また、Unicodeなどの一部の文字セットは引き続き進化しています。現在、コードポイントの範囲は0..0xD7FF、0xE000..0x10FFFFに固定されていますが、ほとんどはまだ割り当てられておらず、新しいバージョンのUnicodeごとに新しいコードポイントの範囲が割り当てられ、システムベンダーはこれに合わせて努力しています。

graphとして分類された文字は、ISO / IEC TR 14652(2002)の後継であるISO / IEC 30112テクニカルレポート(2014)に記載されています。 GNUロケールはこれに従うようですが、他のロケール(FreeBSD / Solarisなど)はそうではありません。しかし、私にはあまり意味がないようだから、彼らを非難するわけではありません。たとえば、ほとんどのスペース文字は除外されますが、U+00A0(単純スペース)、U+2007(数値スペース)、またはU+200B(幅0のスペース)は除外されます。私の考えにはキャラクターが含まれていると思います。コントロールU+200C..U+200F, U+202D, U+202E...² のような文字カバーは右から左へこのQ&Aで重要なのは、文字の順序が左から右に変わることです。

$ printf '%b\n' '\u202E' a b c | sort | paste -sd '\0' -
‮abc

(一部のブラウザではサポートされているかどうかcba、他のブラウザではサポートされているかどうかが表示されますabc)。

また、ほとんどのコンテンツが含まれます。商標数値何千もの使用システムに描画できるのはもちろん、割り当てられる可能性もない文字です。

シングルバイト文字セット(GNUシステムではlocale ctype-mb-cur-max1を返す文字セット)の場合、グラフィック文字のリストはすべての255バイト値を繰り返す必要があります(最初を無視すると、各文字セットのNULはグラフィック文字セットではありません。)問題が発生する可能)と一致させます[[:graph:]]

awkたとえば、次のようにできます。

awk '
  BEGIN{
    for (i = 1; i < 256; i++) {
      c = sprintf("%c", i)
      if (c ~ /[[:graph:]]/) print c
    }
  }' | sort | paste -sd '\0' -

iso8859-7 シングルバイト文字セットを使用するギリシャ語ロケールでは、el_GR.iso88597以下が提供されます。

`^¨~<=>¦°_­-,;:!?/.·'ʽʼ"«»()[]{}§©@$£¤¥*\&#%+±ª―΄΅0½12²3³456789aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZΑαΆάΒβΓγΔδΕεΈέΖζΗηΉήΘθΙιΊίΪϊΐΚκΛλΜμΝνΞξΟοΌόΠπΡρΣσςΤτΥυΎύΫϋΰΦφΧχΨψΩωΏώ 

(後に続く切り捨て防止スペースは、GNUロケールの「グラフィック」として誤って分類されます。)

この方法はマルチバイト文字では使用できません。

または、文字セットエンコーディングをiconvサポートしている場合は、すべてのUnicodeコードポイントを32ビットのビッグエンディアン数で生成し、それをロケールの文字セットに変換できます。UCS-4BEUTF32BE

perl -e 'print pack("L>*", $_, 10) for 1..0xd7ff, 0xe000..0x10ffff' |
  iconv -cf UCS-4BE |
  grep '[[:graph:]]' |
  sort

またはUTF-8をサポートしている場合:

perl -C -M-warnings=nonchar -le 'print chr$_ for 1..0xd7ff, 0xe000..0x10ffff' |
  iconv -cf UTF-8 |
  grep '[[:graph:]]' |
  sort

(上記の問題を回避し、行が長すぎるのを防ぐために、1行に1文字ずつ予約してください。)

これは、Unicode(および対応するエンコード)が他のすべての可能な文字セットの文字を含むように設計されているため、すべての文字セット内のすべての文字には常にUnicodeコードポイントがあります。最新のシステムは、実際にはUnicodeの点で文字セットを定義し、通常はwchar_tUnicodeコードポイントに対応します。

上記のように、ソートはソートとmemcmp()同じ文字比較に基づく比較を使用しますstrcoll()。シングルバイト文字セットの場合、その文字セット内のコードポイントに基づいてソートされます。 UTF-8の場合、UTF-8には特定の属性があるため、Unicodeコードポイントに基づいてソートされます。他のUnicodeエンコーディング(中国語GB18030や他のマルチバイト文字セットなど)の場合、これは多少ランダムに表示されることがあります。

それにもかかわらず、これは、ソート順が同じ2つのロケールの場合、そのsortロケールが異なる文字セットを使用すると出力が異なることを意味します。

例えば、① ② ③ ④ ⑤ ⑥ ⑦ ─ ⑩⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳ 丸められた数字に戻ると。 Unicodeはこれを対応する順序(コードポイント0x2460〜0x2473)で指定します。 GNUロケールでは順序は定義されていません(①が②よりも前も後もありません)。 UTF-8を使用するロケールでは、UTF-8の順序はUnicodeコードポイントの順序に従うので、①の後に②をソートします。ただし、GB18030(中国の別のUnicodeエンコーディング)を使用するzh_CN.gb18030などのロケールでは、文字がバイトレベルでエンコードされる方法に応じて、⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳123456789⑩このエラーこれにより、手順は①②②③④⑤⑥⑧⑩⑮⑯⑰⑱⑲⑳⑪⑫⑬⑭)です。

照合順序に従って文字列の文字を並べ替えるには、次のようにしますzsh

printf "%s\n" ${(j::)${(s::o)string}}

zshは変数にNUL文字を含めることができますが、strcoll()これらの文字では機能しません。zshこの問題を解決しようとしましたが、完璧ではない

文字列に同じソート順を持つ別の文字が含まれている場合、結果は定義されません。


^2019年編集新しいバージョンのGNU libcでは、①②②③④⑤の順序が修正されましたが、2.30現在95%以上の文字がまだ定義されている順序はありません。

おすすめ記事