パイプ「|」で行をソートせずにソート その中に正しく


17

パイプで区切られた単純なデータを並べ替えようとしています。ただし、並べ替えは実​​際には並べ替えではありません。ヘッダー行を下に移動しますが、241で始まる2つの行は24で始まる行で分割されています。

cat sort_fail.csv
column_a|column_b|column_c
241|212|20810378
24|121|2810172
241|213|20810376

sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

列ヘッダーはファイルの下部に移動されているため、並べ替えが明らかに処理しています。しかし、実際の値は私が期待するようにソートされていません。

この場合、私はそれを回避しました

sort sort_fail.csv --field-separator='|' -k1,1

しかし、それは必要ではないように感じます。ソートがソートではないのはなぜですか?


2
を使用しますLC_COLLATE=C sort。あなたが期待している内容に応じて、あなたはまた、必要があるかもしれないLC_COLLATE=C sort -t'|' -n
mosvy

3
「csvスタイル」データを並べ替えるにcsvsortcsvkit、引用された値を適切に処理するfrom を使用できます。
バクリウ

回答:


32

sort ロケールに対応しているため、LC_COLLATE設定(LANGから継承)に応じて、異なる結果が得られる場合があります。

$ LANG=C sort sort_fail.csv 
241|212|20810378
241|213|20810376
24|121|2810172
column_a|column_b|column_c

$ LANG=en_US sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

これはスクリプトで問題を引き起こす可能性があります。呼び出しロケールが設定されていることに気付かない可能性があり、異なる結果が得られる可能性があるためです。

スクリプトが必要な設定を強制することは珍しくありません

例えば

$ grep 'LC.*sort' /bin/precat
      LC_COLLATE=C sort -u | prezip-bin -z "$cmd: $2"

ここで面白いのは、|キャラクターが奇妙に見えることです。

しかし、それは、ISOから派生したen_USのデフォルトルールが言うためです。

$ grep 007C /usr/share/i18n/locales/iso14651_t1_common
<U007C> IGNORE;IGNORE;IGNORE;<j> # 142 |

つまり、|文字は無視され、ソート順は文字が存在しないかのようになります。

$ tr -d '|' < sort_fail.csv | LANG=C sort
24121220810378
241212810172
24121320810376
column_acolumn_bcolumn_c

そして、それはあなたが見ている「予期しない」ソートと一致します。

回避策は、使用する-n(数値ソートを強制する)か、フィールド区切り文字を使用する(実行した)か、Cロケールを使用することです。


魅力的です。ローカリゼーションに関する他のヒットを見ましたが、それは24対241の相対的な順序に影響を与えると考えました。このようなものではありません。
user10777668

7
GNU内の余分な便利なものは一種である--debug比較するために使用するキーを(下線)を示すオプション、
ジェフ・シャラー

--debugで実行すると、行全体に下線が引かれます-並べ替えにはパイ​​プ文字が含まれ、ローカライズのために影響を与えないように設定されています。それは良い機能ですが、このケースでは私を助けませんでした(私が試しました:)
user10777668

それがまさに@ user10777668に言及した理由です- sort想定されている文字で停止するのではなく、行全体を使用していることを示しています。
ジェフシャラー

止まるとは思っていませんでした。パイプ文字を認識し、その文字をソートに含めることを期待していたため、24 | 1と241を別々に処理します。--debugがそれをどのように変更したかはわかりませんが、実際に| それは積極的に局在化は、パイプ文字がingoredされることにつながった本当の問題から気を取られていたように思える
user10777668

1

私をイライラさせるのは24、2つの間の場所から動かないこと241です。2番目のフィールドはで始まり1ます。42番目のフィールドに先頭を付けて並べ替えを試みると、24が下に移動するためsort|特に指示がない限り、単に無視すると思われます。試してみてくださいsort -n...


1

-n、-numeric-sortは文字列の数値に従って比較します

210
23

-nを指定しないと、文字ごとに210が23よりも先になります。


あなたは正しいですが、これはパイプ文字が異なることを説明していません。他の答えは、ロケールのために、パイプはそこにないものとして扱われ、次の数字が順序を決定するものであることを示しています。
クリギー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.