Geben Sie die Sortierreihenfolge mit LC_COLLATE an, sodass Kleinbuchstaben vor Großbuchstaben stehen

16

Angesichts der Datei:

$ cat file
1
a
C
B
2
c
3
A
b

Standardmäßig sortwird:

$ sort file
1
2
3
a
A
b
B
c
C

Mit LC_COLLATE=Cso wird in Großbuchstaben vor Kleinbuchstaben sortiert:

$ LC_COLLATE=C sort file
1
2
3
A
B
C
a
b
c

Ist es möglich, sortieren zu lassen, um die Reihenfolge der Groß- und Kleinschreibung umzukehren?

iiSeymour
quelle

Antworten:

8

Ich kenne keine Ländereinstellungen, die standardmäßig in dieser Reihenfolge sortiert sind. Die Lösung besteht darin, ein benutzerdefiniertes Gebietsschema mit einer benutzerdefinierten Sortierreihenfolge zu erstellen. Wenn jemand vier Jahre später auf eine benutzerdefinierte Weise sortieren möchte, ist hier der Trick.

Die überwiegende Mehrheit der Gebietsschemas gibt keine eigene Sortierreihenfolge an, sondern kopiert die in definierte Sortierreihenfolge, /usr/share/i18n/locales/iso14651_t1_commonsodass Sie diese bearbeiten möchten. Anstatt die Sortierreihenfolge für fast jedes Gebietsschema durch Ändern des Originals zu ändern iso14651_t1_common, sollten Sie eine Kopie erstellen. Details zur Funktionsweise der Sortierreihenfolge und zum Erstellen eines benutzerdefinierten Gebietsschemas in Ihrem $HOMEVerzeichnis ohne Root-Zugriff finden Sie in dieser Antwort auf eine ähnliche Frage .

Werfen Sie einen Blick darauf, wie aund Awerden basierend auf ihren Einträgen in bestellt iso14651_t1_common:

<U0061> <a>;<BAS>;<MIN>;IGNORE # 198 a
<U0041> <a>;<BAS>;<CAP>;IGNORE # 517 A

bund Bsind ähnlich:

<U0062> <b>;<BAS>;<MIN>;IGNORE # 233 b
<U0042> <b>;<BAS>;<CAP>;IGNORE # 550 B

Wir sehen, dass beim ersten Durchgang beide aund Adas Sortiersymbol haben <a>, während beide bund Bdas Sortiersymbol haben <b>. Da <a>erscheint vor <b>in iso14651_t1_common, aund Asind vor bund gebunden B. Der zweite Durchgang unterbricht die Verbindungen nicht, da alle vier Zeichen das Sortiersymbol <BAS>haben. Während des dritten Durchgangs werden die Verbindungen jedoch aufgelöst, da das Sortiersymbol für Kleinbuchstaben <MIN>in Zeile 3467 vor dem Sortiersymbol für Großbuchstaben <CAP>(Zeile 3488) angezeigt wird. . So ist die Sortierreihenfolge so endet a, A, b, B.

Das Vertauschen des ersten und dritten Sortiersymbols sortiert die Buchstaben zuerst nach Groß- und Kleinschreibung (unterer als oberer Buchstabe), dann nach Akzent ( <BAS>bedeutet nicht akzentuiert) und dann nach alphabetischer Reihenfolge. Befinden sich jedoch beide <MIN>und <CAP>vor den numerischen Ziffern, so würde dies den unerwünschten Effekt haben, Ziffern nach Buchstaben zu setzen.

Die einfachste Möglichkeit, die ersten Ziffern zu behalten, während alle Kleinbuchstaben vor allen Großbuchstaben kommen, besteht darin, alle Buchstaben beim ersten Vergleich zum Binden zu zwingen, indem Sie alle auf gleich setzen <a>. Um sicherzustellen, dass sie innerhalb der Groß- und Kleinschreibung alphabetisch sortiert sind, ändern Sie das letzte Sortiersymbol von IGNOREin das aktuelle erste Sortiersymbol. Nach diesem Muster awürde werden:

<U0061> <a>;<BAS>;<MIN>;<a> # 198 a

A würde werden:

<U0041> <a>;<BAS>;<CAP>;<a> # 517 A

b würde werden:

<U0062> <a>;<BAS>;<MIN>;<b> # 233 b

B würde werden:

<U0042> <a>;<BAS>;<CAP>;<b> # 550 B

und so weiter für den Rest der Briefe.

iso14651_t1_commonBefolgen Sie nach dem Erstellen einer benutzerdefinierten Version von die Anweisungen in der oben verlinkten Antwort , um Ihr benutzerdefiniertes Gebietsschema zu kompilieren.

Bohnendip
quelle
6

Die Einstellung reicht LC_COLLATE=Cnicht immer aus, um Großbuchstaben vor Kleinbuchstaben zu sortieren. Möglicherweise müssen Sie festlegen LC_ALL=C.

Dabei werden auch nicht alphanumerische und sogar nicht druckbare Zeichen berücksichtigt. Wenn Sie dies jedoch nicht möchten, stehen Optionen zur Verfügung, -dmit denen Sie -i(wie in beschrieben man sort) das deaktivieren können.

Bei Multibyte-Eingaben wie UTF-8 mit Nicht-ASCII-Zeichen schlägt dies wahrscheinlich fehl.

Um Kleinbuchstaben (in der richtigen Reihenfolge) vor Großbuchstaben (in der richtigen Reihenfolge) zu erhalten, muss die Groß- und Kleinschreibung aller Buchstaben vor der Sortierung invertiert und umgekehrt werden danach.

tr 'a-zA-Z' 'A-Za-z' < file | LC_ALL=C sort | tr 'a-zA-Z' 'A-Za-z'
Law29
quelle
2

Ich bin kein Experte, aber ich habe noch nie ein Gebietsschema gesehen, das eine solche Sortierung definiert. AFAIK diese Kollatierung ist nur in C, wo es auf ASCII-Werten basiert . (Normalerweise würde ich das nur durch ein Skript lösen.)

Ich habe dies jedoch noch nie getan, aber Sie sollten sich die Hilfeseiten localedef (1) und locale (5) ansehen, um zu verstehen, wie Gebietsschemas definiert sind, und schließlich Ihre eigene definieren.

Vergessen Sie auch nicht, dass das Gebietsschema C diakritische Zeichen oder Sonderzeichen nicht so behandelt, wie Sie es möchten. Zum Beispiel wird es nicht in der áNähe aoder in der ŁNähe setzen L. In solchen Fällen wäre das Gebietsschema der Sprache wahrscheinlich ein besserer Ausgangspunkt.

Alois Mahdal
quelle
0

Ich glaube, die Antwort ist, ohne dass LC_COLLATE geändert werden muss (was bedeutet, dass die Funktion als Standardverhalten belassen wird):

sort -f file

Dies funktioniert unter Linux. Informationen zum Befehl finden Sie in Ihrem Hilfeabschnitt, falls Sie unter Unix arbeiten und eine andere Version ausführen. -f wird als Groß- / Kleinschreibung ignorierend definiert.

Vielen Dank für die recht (und merkwürdigerweise) schnelle Korrektur und Bearbeitung der falsch platzierten Grammatik, Stephen Rauch.

1,0 g
quelle
-1
LC_COLLATE="en_US.UTF-8" sort file
entmutigen
quelle
Dies sortiert keine Kleinbuchstaben vor Großbuchstaben? ideone.com/Gtyg4Z
iiSeymour
Hmm, in meinem Fall hat es Ihr Beispiel verwendet.
Unxnut
4
@unxnut Das ist falsch. Ohne das Semikolon würde der Befehl die Umgebung für festlegen sort, aber mit dem Semikolon ist die Variable lokal für die Shell und hat keinen Einfluss auf das Verhalten von sort. Das Semikolon könnte so bleiben, wie es ist, wenn die Variable ebenfalls exportiert wird, dies würde jedoch auch andere Befehle betreffen.
Anders Sjöqvist