次の内容を含むファイルから重複した行を削除したいと思います。シリア語スクリプト。ソースファイルには3行があり、最初と3行は同じです。
$ cat file.txt
ܐܒܘܢ
ܢܗܘܐ
ܐܒܘܢ
sort
andを使用すると、uniq
結果は3つの行がすべて同じであると仮定しますが、これは間違っています。
$ cat file.txt | sort | uniq -c
3 ܐܒܘܢ
ロケールを明示的にシリア語に設定することも役に立ちません。
$ LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c
3 ܐܒܘܢ
なぜこれが起こるのですか?それが重要であれば、私はKubuntu 18とbashを使用しています。
ベストアンサー1
uniq
-c
UbuntuでのGNUの実装まったく同じ行ですが、同じ順序の連続行数です。
GNUシステムのほとんどの国際ロケールには、完全に関連していない多くの文字が同じソート順で定義されるバグがあります。ほとんどは、ソート順がまったく定義されていないためです。他のほとんどのオペレーティングシステムでは、すべての文字のソート順が異なります。
$ expr ܐ = ܒ
1
(expr
演算子=
、数値以外の引数の場合、オペランドの順序が等しい場合は1を返し、それ以外の場合は0を返します)。
ar_SY.UTF-8
これはまたはと同じですen_GB.UTF-8
。
必要なのは、これらの文字に異なる並べ替え順序が付与されたロケールです。 Ubuntuにシリア言語のロケールがある場合、これらの文字には別のソート順序が付与されると予想できますが、Ubuntuにはそのようなロケールはありません。
locale -a
サポートされているロケールリストの出力を表示できます。dpkg-reconfigure locales
として実行して、より多くのロケールを有効にできますroot
。localedef
の定義ファイルに基づいてより多くのロケールを手動で定義することもできますが、/usr/share/i18n/locales
シリア語のデータは見つかりません。
次の点に注意してください。
LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c
コマンドにLC_COLLATE変数を設定するだけです。cat
これはファイルの内容の出力方法に影響を与えず、cat
テキストユーティリティではないため、コントラストや文字エンコーディングにも興味がありません。sort
との両方を設定しようとしていますuniq
。また、LC_CTYPE
UTF-8文字セットを使用してロケールを設定する必要があります。
システムにロケールがないため、これはsyr_SY.utf8
ロケール(デフォルトロケール)を使用するのと同じです。C
実際、ここのCロケールまたはC.UTF-8はおそらく使用したいロケールです。
これらのロケールでは、組み合わせ順序はコードポイント、C.UTF-8のUnicodeコードポイント、Cのバイト値に基づいていますが、最終的にはその属性を使用するUTF-8文字エンコーディングと同じです。
$ LC_ALL=C expr ܐ = ܒ
0
$ LC_ALL=C.UTF-8 expr ܐ = ܒ
0
だから:
(export LANG=ar_SY.UTF-8 LC_COLLATE=C.UTF-8 LANGUAGE=syr:ar:en
unset LC_ALL
sort <file | uniq -c)
文字セットとしてUTF-8を含むLC_CTYPE、コードポイントベースのソート順序、およびシリア語またはアラビア語のエラーメッセージ(GNU coreutilsまたはメッセージがその言語に翻訳されているsort
場合uniq
)などのロケールに関連するその他の設定があります。まだ持っていません)。
これらを気にしない場合その他設定と使いやすさとポータブルに優れています。
<file LC_ALL=C sort | LC_ALL=C uniq -c
または
(export LC_ALL=C; <file sort | uniq -c)
@isaacがすでに示したように。
1 POSIX準拠のuniq
実装は、ロケールソートアルゴリズムを使用した文字列比較ではなく、バイト間の同等比較を意味します。これは2018年版の標準でより明確になりました(参照:対応するオースティングループエラー)。しかし、GNUはuniq
現在これを使用しており、strcoll()
大文字と小文字を区別しない比較オプションがPOSIXLY_CORRECT
あります。-i
これは皮肉なことに、ロケール情報を使用せずにASCII入力でのみ正しく機能します。