Sortiere nicht sortiere Zeilen mit einem Pipe '|' darin richtig

17

Ich versuche, einige einfache, durch Pipes getrennte Daten zu sortieren. Sort ist jedoch nicht wirklich sortieren. Es verschiebt meine Kopfzeile nach unten, aber meine zwei mit 241 beginnenden Zeilen werden durch eine mit 24 beginnende Zeile geteilt.

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

Die Spaltenüberschriften werden an den unteren Rand der Datei verschoben, sodass die Sortierung diese eindeutig verarbeitet. Die tatsächlichen Werte werden jedoch nicht wie erwartet sortiert.

In diesem Fall habe ich damit herumgearbeitet

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

Aber ich denke, das sollte nicht nötig sein. Warum wird nicht sortiert?

user10777668
quelle
2
verwenden LC_COLLATE=C sort. Je nachdem, was Sie erwarten, benötigen Sie möglicherweise auchLC_COLLATE=C sort -t'|' -n
mosvy
3
Um „csv Stil“ Daten sortieren können Sie verwenden möchten, csvsortaus csvkit, die Werte Griffe richtig zitiert.
Bakuriu

Antworten:

32

sort Da das Gebietsschema berücksichtigt wird, erhalten Sie abhängig von Ihrer LC_COLLATE-Einstellung (die von LANG geerbt wird) möglicherweise unterschiedliche Ergebnisse:

$ 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

Dies kann zu Problemen in Skripten führen, da Sie möglicherweise nicht wissen, auf welches Gebietsschema das aufrufende Gebietsschema festgelegt ist, und daher möglicherweise unterschiedliche Ergebnisse erzielen.

Es ist nicht ungewöhnlich, dass Skripte die erforderlichen Einstellungen erzwingen

z.B

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

Das Interessante hier ist, dass die |Figur seltsam aussieht.

Aber das liegt daran, dass die von ISO abgeleitete Standardregel für en_US lautet

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

Das bedeutet, dass das |Zeichen ignoriert wird und die Sortierreihenfolge so ist, als ob das Zeichen nicht existiert.

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

Und das entspricht der "unerwarteten" Sortierung, die Sie sehen.

Die Umgehungsmöglichkeiten bestehen darin -n, numerische Sortierungen zu erzwingen oder das Feldtrennzeichen zu verwenden (wie Sie es getan haben) oder das CGebietsschema zu verwenden.

Stephen Harris
quelle
Faszinierend. Ich habe einige andere Treffer zur Lokalisierung gesehen, aber es wurde angenommen, dass dies die relative Reihenfolge von 24 zu 241 beeinflussen würde, nicht so etwas.
user10777668
7
Etwas besonders Nützliches bei der GNU-Sortierung ist die --debugOption, die den (unterstrichenen) Schlüssel angibt, der zum Vergleichen verwendet wird
Jeff Schaller
Wenn Sie mit --debug ausgeführt werden, wird die gesamte Zeile unterstrichen. Die Sortierung enthält auch das Pipe-Zeichen. Aufgrund der Lokalisierung hat sie nur keine Auswirkungen. Es ist eine gute Funktion, hat mir aber in diesem Fall nicht geholfen (ich habe es versucht :)
user10777668
Genau deshalb habe ich es erwähnt, @ user10777668 - es zeigt an, dass sortdie gesamte Zeile verwendet wird, anstatt bei Zeichen anzuhalten, von denen wir annehmen , dass dies der Fall ist.
Jeff Schaller
Ich hatte nicht damit gerechnet, dass es aufhört. Ich hatte erwartet, dass es den Pipe-Charakter erkennt und diesen in die Sortierung einbezieht, weshalb 24 | 1 und 241 unterschiedlich behandelt werden. Ich bin nicht sicher, wie --debug das geändert hätte, und in der Tat, da es die | unterstreicht Es scheint, als wäre es aktiv von dem eigentlichen Problem abgelenkt worden, bei dem die Lokalisierung dazu geführt hat, dass der Pipe-Charakter eingebettet wurde
user10777668
1

Was mich irritiert ist, dass sich das 24nicht von seinem Platz zwischen den beiden bewegt 241. Das zweite Feld beginnt mit einem 1. Versucht man die Sortierung mit einem Anführungszeichen 4im zweiten Feld, wird das 24nach unten verschoben, weshalb ich den Verdacht habe, das sorteinfach zu ignorieren, |sofern nicht anders angegeben. Versuchen Sie sort -n...

RudiC
quelle
1

-n, --numeric-sort vergleiche nach dem Zahlenwert der Zeichenkette

210
23

Ohne das -n steht 210 by text vor 23, wenn es um mein Zeichen geht.

michaelkrieger
quelle
Du hast recht, aber das erklärt nicht, dass der Pipe Char anders ist. Die anderen Antworten zeigen, dass die Pipe aufgrund des Gebietsschemas als nicht vorhanden behandelt wird, sodass die nächste Ziffer über die Reihenfolge entscheidet.
Criggie