LC_ALL=C は破壊的ですか?

LC_ALL=C は破壊的ですか?

かなり大きな (約 15 GB) テキスト ファイルのセットがあります。これらのファイルは基本的に資格情報を含む単純なデータベースであり、その中の資格情報は 128 文字の ASCII 範囲外 (アクセント付き文字など) であることがよくあります。

これらのファイルの一部を次のように並べ替えようとすると、

sort -u input.txt -o output.txt

...次のエラーが発生します:

sort: string comparison failed: Invalid or incomplete multibyte or wide character
sort: Set LC_ALL='C' to work around the problem.

を使用すると、やなどLC_ALL=Cの文字を扱うコマンドを高速化できるという記事をたくさん読んだことがあります。sortgrepステファン・シャゼラスの素晴らしい答えこのトピックについては、特に自分のデータセットでそれを使用することの影響について心配しています。

これらのファイルを実行するLC_ALL=C sort -uと、非 ASCII 文字が削除される可能性はありますか?

もしそれが、代わりにすべてを修正/削除するにはどうすればいいでしょうか?無効または不完全なマルチバイト文字またはワイド文字「これらのファイルから」を削除し、LC_ALL=C?を使用せずに並べ替えることができます。

答え1

これらのファイルに対して LC_ALL=C sort -u を実行すると、非 ASCII 文字が削除される可能性はありますか?

この場合はそうではありません。sortバイト値を文字に変換しようとするのではなく、バイト値を直接処理します。

ただし、同じことが他のツールに必ずしも当てはまるわけではありません。C (言語) で書かれたプログラムは、このように動作する可能性が最も高くなります。Python 3 などの、バイトと文字の区別が明確な言語で書かれたプログラムは、文字セットに準拠しない入力を完全に拒否する必要があります。また、エラーを無視して?代わりに � または を出力するような、下手に書かれたプログラムも想像できます。

もしそうなら、これらのファイルからすべての「無効または不完全なマルチバイトまたはワイド文字」を修正/削除して、LC_ALL=C を使用せずに並べ替えられるようにするには、代わりに何ができるでしょうか?

すべて同じファイル エンコーディング (UTF-8 が望ましい) が使用されていること、およびロケールで同じエンコーディングが使用されていることを確認してください。有効な UTF-8 ファイルであれば、ファイルの大きさに関係なく、エラーが発生することはありません。

答え2

sort、、、などgrepのさまざまな Bash ツールにファイルをパイプする必要が生じたため、承認された回答に示されている「適切な解決策」、つまり最初にすべてを UTF-8 に変換する方が安全だと判断しました。これは予想よりも少し難しくなりましたが、ファイルが ASCII かUTF-8 かを判断するのに が信頼できないことに気づくのにしばらく時間がかかりました (ファイル全体をチェックしないため)。そのため、後世のためにこの回答をここに掲載します。awkwctrfile

ファイルのエンコーディングを確実に判断するには、まずuchardetパッケージがCygwinインストーラー経由でインストールされていることを確認するか、apt-cygを実行し、以下を実行します。

uchardet *.txt

または、Cygwin を使用していない場合は、次のようになります。

chardet *.txt 

chardetリストされているすべてのファイルをASCII独自のフォルダーに移動し、forそのフォルダーで次のループを実行します。

for i in *.txt; do iconv -f ASCII -t UTF-8 "$i" >> "${i%.txt}_utf.txt"; done;

.txtフォルダー内のすべてのファイルをループし、utfサフィックスが追加された UTF-8 バージョンを作成します。

再度実行するとuchardet *.txt、一部のファイルが と表示されることがありますASCII。これは、ASCIIがUTF-8のサブセットであるためです。単にこれらのファイルには、128 ビットの ASCII 範囲外の文字が含まれていないことを確認します。

sortこれで、を使用せずに実行できるはずですLC_ALL=C

関連情報