Warum sagt sort, dass ɛ = e ist?


25

ɛ("Latin epsilon") ist ein Buchstabe, der in bestimmten afrikanischen Sprachen verwendet wird und normalerweise den Vokalton im englischen "Bett" darstellt. In Unicode wird es als U + 025B codiert, ganz anders als im Alltag e.

Wenn ich aber sortfolgendes:

eb
ed
ɛa
ɛc

es scheint, dass sortberücksichtigt ɛund egleichwertig:

ɛa
eb
ɛc
ed

Was ist hier los? Und ist es eine Möglichkeit zu machen ɛund everschiedene für sortZwecke ing?


21
Sortierregeln werden "Kollation" genannt, wenn das Ihrem
Googeln

1
Versuchen Sie, eine bestimmte Anzahl von eaMischen mit ɛain eine Textdatei zu setzen und sie zu sortieren. Sie werden sehen, dass es immer eavorher sortiert ɛa. Also, nein, sie werden nicht als gleich angesehen.
Bakuriu

Könnte ein naheliegender Punkt sein, aber ich habe noch keinen expliziten Vorschlag gesehen: Wenn Sie Wörter in $ (bestimmte_afrikanische_Sprache) sortieren, ist es das Natürlichste, das Gebietsschema auf $ (bestimmte_afrikanische_Sprache) zu setzen.
Federico Poloni

@ FedericoPoloni Ein sehr guter Punkt! Leider konnte ich kein Gebietsschema für diese Sprache finden.
Draconis

1
@ GermánBouzas Dies ist speziell das "lateinische Epsilon", eine Form, die dem lateinischen Alphabet entspricht. Sie sehen fast gleich aus, aber das lateinische epsilon ist U + 025B, während das griechische epsilon U + 03B5 ist.
Draconis

Antworten:


67

Nein, es betrachtet sie nicht als äquivalent, sie haben nur das gleiche Primärgewicht. Damit sortieren sie in erster Näherung gleich.

Wenn Sie sich / usr / share / i18n / locales / iso14651_t1_common (als Grundlage für die meisten Gebietsschemas) auf einem GNU-System ansehen (hier mit glibc 2.27), werden Sie sehen:

<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U025B> <e>;<PCL>;<MIN>;IGNORE # 287 ɛ
<U0045> <e>;<BAS>;<CAP>;IGNORE # 577 E

e, ɛUnd Edas gleiche Gewicht haben , primäres, eund Egleiche Sekundär Gewicht, nur das dritte Gewicht unterscheidet sie.

Beim Vergleichen von Strings sort(die strcoll()Standard-libc-Funktion dient zum Vergleichen von Strings) werden zunächst die primären Gewichte aller Zeichen verglichen. Das zweite Gewicht wird nur dann verwendet, wenn die Strings mit den primären Gewichten (und so weiter mit den anderen Gewichten) übereinstimmen. .

So scheint Groß- / Kleinschreibung in der Sortierreihenfolge in erster Näherung ignoriert zu werden. Absortiert zwischen aaund ac, Abkann aber abje nach Sprachregel vor oder nach sortieren (manche Sprachen haben <MIN>vorher <CAP>wie im britischen Englisch, manche <CAP>vorher <MIN>wie im estnischen).

Wenn Sie edieselbe Sortierreihenfolge wie haben ɛ, wird printf '%s\n' e ɛ | sort -unur eine Zeile zurückgegeben. Aber wie <BAS>vorher sortiert <PCL>, esortiert allein vorher ɛ . eɛesortiert nach EEE(beim Sekundärgewicht), obwohl EEEsortiert nach eee(für das wir zum dritten Gewicht aufsteigen müssen).

Wenn ich nun mit glibc 2.27 auf meinem System arbeite, führe ich Folgendes aus:

sed -n 's/\(.*;[^[:blank:]]*\).*/\1/p' /usr/share/i18n/locales/iso14651_t1_common |
  sort -k2 | uniq -Df1

Sie werden feststellen, dass es einige Zeichen gibt, die mit genau den gleichen 4 Gewichten definiert wurden. Insbesondere hat unser ɛ die gleichen Gewichte wie:

<U01DD> <e>;<PCL>;<MIN>;IGNORE
<U0259> <e>;<PCL>;<MIN>;IGNORE
<U025B> <e>;<PCL>;<MIN>;IGNORE

Und sicher genug:

$ printf '%s\n' $'\u01DD' $'\u0259' $'\u025B' | sort -u
ǝ
$ expr ɛ = ǝ
1

Dies kann als Fehler in GNU libc-Gebietsschemas angesehen werden. Auf den meisten anderen Systemen stellen Gebietsschemas sicher, dass alle unterschiedlichen Zeichen am Ende eine unterschiedliche Sortierreihenfolge haben. Auf GNU locales, wird es noch schlimmer, da es Tausende von Zeichen, die alle möglichen Probleme nicht über eine Sortierreihenfolge haben und verursacht, die gleiche Sortierung am Ende (wie Bruch comm, join, lsoder Kleckse mit nicht-deterministisch Aufträge ... ), daher die Empfehlung der Verwendung LC_ALL=Cdieser Probleme zu umgehen .

Wie von @ninjalj in Kommentaren angemerkt, brachte die im August 2018 veröffentlichte glibc 2.28 einige Verbesserungen in dieser Hinsicht mit sich, obwohl AFAICS noch einige Zeichen oder Sortierelemente mit identischer Sortierreihenfolge definiert hat. Unter Ubuntu 18.10 mit glibc 2.28 und in einem Gebietsschema von en_GB.UTF-8.

$ expr $'L\ub7' = $'L\u387'
1

(Warum wird U + 00B7 nur in Kombination mit L/ als U + 0387 gleichgesetzt l?!).

Und:

$ perl -lC -e 'for($i=0; $i<0x110000; $i++) {$i = 0xe000 if $i == 0xd800; print chr($i)}' | sort > all-chars-sorted
$ uniq -d all-chars-sorted | wc -l
4
$ uniq -D all-chars-sorted | wc -l
1061355

(immer noch mehr als 1 Million Zeichen (95% des Unicode-Bereichs, gegenüber 98% in 2.27), wobei die Sortierung mit anderen Zeichen identisch ist, da ihre Sortierreihenfolge nicht definiert ist).

Siehe auch:


3
Genau das habe ich gesucht! Wofür steht der Vollständigkeit <PCL>halber? Die anderen scheinen Capital, Miniscule und Basic zu sein?
Draconis

3
@ Draconis, Sortier -Symbol <PCL> # 16 besonders / eigenartig
Stéphane Chazelas

In der Tat, wenn wir ein Bündel von eaund ɛagemischt in einer Datei sehen wir, dass sortalle eas vor ɛas sortiert .
Bakuriu

2
Sehen von glibc 2.28 sollte die Codepoint als Ausweich für eine vierte Ebene Gewicht verwendet werden, sourceware.org/git/... sourceware.org/bugzilla/show_bug.cgi?id=14095
ninjalj

1
@cat, sorry, ich meinte strcoll(), siehe bearbeiten.
Stéphane Chazelas

15

Mann Art:

   ***  WARNING  ***  The locale specified by the environment affects sort
   order.  Set LC_ALL=C to get the traditional sort order that uses native
   byte values.

Also versuche: LC_ALL=C sort file.txt


1
Das funktioniert! Aber warum betrachtet das Standardgebietsschema diese vollständig getrennten Codepunkte als gleich? Ich bin gespannt, warum das passiert.
Draconis

@Draconis Was ist "das Standardgebietsschema"?
Kamil Maciorowski

@KamilMaciorowski Ein leerer Wert der Umgebungsvariablen. Ich bin nicht sicher, welchem ​​Gebietsschema das entspricht.
Draconis

3
Wenn @Draconis LC_ALLleer ist, werden sortmöglicherweise andere LC_*Variablen LANGoder einige Konfigurationsdateien verwendet.
NieDzejkob

1
LC_COLLATEist die string-sort-spezifische, LANGdie extra-allgemeine.
ShadowRanger

8

Das Zeichen ɛ ist nicht gleich e, aber einige Gebietsschemata können diese Zeichen bei der Sortierung nahe beieinander sammeln. Der Grund dafür ist sprachspezifisch, aber auch ein historischer oder gar politischer Hintergrund. Zum Beispiel erwarten die meisten Leute wahrscheinlich, dass die Euro-Uro-Währung im Wörterbuch Europa nahe kommt .

Wie auch immer, um zu sehen, welche Sortierung Sie gerade verwenden locale, locale -awird Ihnen die Liste der auf dem System verfügbaren Gebietsschemas angezeigt und die CSortierung kann für einen Sortierungslauf geändert werden LC_COLLATE=C sort file. Um zu sehen, wie verschiedene Gebietsschemas Ihre Datei sortieren können, versuchen Sie es schließlich

for loc in $(locale -a)
    do echo ____"${loc}"____
    LC_COLLATE="$loc" sort file
done

Leiten Sie das Ergebnis an ein Greping-Tool weiter, um das Gebietsschema auszuwählen, das Ihren Anforderungen entspricht.


Dies ist eine wunderbare Erklärung, aber die Symbole scheinen identisch zu sein und nicht nur nahe beieinander.
Draconis

1
Nein, sie werden nicht als identisch angesehen. Fügen Sie eader Datei eine einfache Linie hinzu, dann erhalten sort -uSie mit beides eaund ɛain der Ausgabe. Die beste Strategie gegen Sortieren ist avoid ( export LC_COLLATE=C). Andernfalls werden viele hässliche Dinge passieren (zB. /tmp/[a-z]In bashpasst auf /tmp/aund /tmp/Aaber nicht /tmp/Z).
Mosvy

@mosvy Huh, interessant ... also werden sie für Bestellzwecke als gleich angesehen, aber nicht für Eindeutigkeitszwecke?
Draconis

Sie werden nicht als gleich angesehen. siehe hier eine erklärung dazu.
Mosvy

1
@ninjalj, das kann in den fnmatch()Bereichen glibc und regexp behoben werden, aber nicht in solchen bash, die ihre Bereiche selbst implementieren strcoll(). ksh93 hatte nie das Problem, da die Bereichsimplementierung strcoll()die Groß- und Kleinschreibung von Bereichsenden verwendet und diese auch überprüft und nur bei Kleinbuchstaben übereinstimmt, wenn beide Enden Kleinbuchstaben sind. Bei zsh-Bereichen tritt das Problem nicht auf, da dies auf der Basis von Codepunkten und nicht auf strcoll () erfolgt.
Stéphane Chazelas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.