
- コンテキスト
- 問題発見
- 質問番号1
- 質問番号2
- 質問番号3
- 質問
コンテキスト
今日は、ファイル内の漢字を含む唯一の行を維持したいと思います。sort
私はこのユーティリティに慣れていて、ファイルから重複行を削除するのがこのフラグを使用するのと同じくらい簡単なので、このユーティリティを使用することにしました-u
。sort
漢字を正しく使用するには、ロケールを変更する必要があることを学びました。私は別のロケールを使ってsort
異なる動作を見つけました。この記事では、私が見つけた結果を紹介します。
ファイルから重複した行を削除することは、複数のツール/プログラミング言語を使用して実行できることを認識しています。これを行うためのツールを提案したすべての人に感謝しますが、ロケールについてさらに学び、これがUnixユーティリティにどのような影響を及ぼすかに興味があります。
問題発見
質問番号1
以下は私のシステムのロケール設定です。
locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
次の名前を考えてください。main.txt
䔍
䏝
私のen_US.UTF-8
行$LANG
番号を失いました。 2
sort -u main.txt
䔍
LANG
設定でこの問題を解決しましたzh_CN.UTF-8
。
export LANG=zh_CN.UTF-8
sort -u main.txt
䔍
䏝
私が作る一つの質問スタックオーバーフローに関するこの質問について。誰かがロケールを変えようと提案したのに効果があるようで問題が解決されたと思ったが後で見たら問題ではないですね。 2と質問番号。 3(以下の説明)。
質問番号2
それでは、ファイルに2行を追加するとしましょう。main.txt
䔍
䏝
答え1
sort -u
出力は、ロケールで同じように(同じソート順に)照合される各行セットの1つです。
GNUシステム(GNU libcを使用するシステム)では、ほとんどのロケールで多くの文字1が定義されていないソート順序を持ち、これは最終的に同じ順序であることを意味し、同じソート順序を持つように明示的に定義された文字もあります。
バイトをテキストとしてデコードできない場合、通常は無視されるか、同じソート順序²を持つと見なされます。
したがって、sort -u
バイト対バイト同等の比較に基づいて一意の行を提供するには、テキストがどのエンコーディングで書かれたかにかかわらず、各バイトを文字としてデコードできるロケールと完全な順序付きロケールが必要です。
最も簡単な方法は、C
バイト==文字マップを持つロケールを使用することです(特定のバイトははっきりしない文字)、ソートはバイト値(少なくともASCIIベースのシステムでは)に基づいており、特定のシステムで見つけることができる唯一のロケールです。
あなたがより良い動作を提供する理由を理解するには、一般的にGNUシステムで見つけることができるロケール定義をzh_CN
見てください。ここで以下を見つけることができます。/usr/share/i18n/locale
zh_CN
LC_COLLATE
copy "iso14651_t1_pinyin"
END LC_COLLATE
どこiso14651_t1_pinyin
:
copy "iso14651_t1_common"
en_US
次に、多くの追加の中国語文字の並べ替えを指定しますiso14651_t1_common
。
zh_CN.GB18030またはzh_CN.GBKに設定LC_CTYPE
(配信LANG
)してUTF-8sort
でエンコードされたファイルを処理しようとすると、通常UTF-8でエンコードされたテキストのバイトがエンコードされないため、その行をテキストにデコードできません。 GB18030エンコーディングで有効なフォーマットを設定すると、問題がさらに悪化します。
ここで一意の(バイト対バイト比較による)行を取得しようとすると同時に、そのロケールで「正しく」ソートされた出力を取得するには、次のようにします。
LC_ALL=C sort -u your-file | sort
1 つ目はsort
重複項目を削除し、2 つ目はロケールのソート規則に従って残りの行をソートします。
LC_ALL
代わりにLANG
or LC_CTYPE
+を使用するLC_COLLATE
理由は、この変数がすべてをオーバーライドする変数(whichよりも優先されます)であるためですLC_ALL
。LC_individual_setting
したがって、LANG
orが環境に異なる方法で設定されていても、LANG
まだLC_COLLATE
機能します。
理論的には、次のようにすることもできます。
LC_ALL= LC_CTYPE=C LC_COLLATE=C sort
「文字タイプ」および「組み合わせ」設定のみが設定され、他のロケールカテゴリはそのままに(またはとして上書きさLANG
れてLC_xxx
)使用される残りのカテゴリは、たとえばエラーメッセージsort
用です。設定すると、USのみが使用されます。とにかく英語のメッセージはASCII文字のみを含むため、正しく表示されます。たとえば、LC_MESSAGES
LC_CTYPE=C
$ LC_MESSAGES=zh_CN LC_CTYPE=C sort --version
sort (GNU coreutils) 9.1
Copyright (C) 2022 Free Software Foundation, Inc.
??? GPLv3+:GNU ???????? 3 ?????? <https://gnu.org/licenses/gpl.html>?
????????:??????????????
?????????,????????
? Mike Haertel ? Paul Eggert ???
詳細は以下で確認できます。
厳密に言えば基本単位ではない。特徴しかし、要素の構成ch
たとえば、特定のチェコ地域間h
または内部で複数の類似した文字で構成できます。i
sort
² GNU以外のいくつかの実装sort
では、NUL文字または過度に長い行もブロックされます。