Ich möchte doppelte Zeilen aus einer Datei mit Wörtern in syrischer Schrift entfernen. Die Quelldatei hat 3 Zeilen, 1. und 3. sind identisch.
$ cat file.txt
ܐܒܘܢ
ܢܗܘܐ
ܐܒܘܢ
Wenn ich sort
verwende und uniq
, geht das Ergebnis davon aus, dass alle 3 Zeilen identisch sind, was falsch ist:
$ cat file.txt | sort | uniq -c
3 ܐܒܘܢ
Das explizite Setzen des Gebietsschemas auf Syrisch hilft auch nicht.
$ LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c
3 ܐܒܘܢ
Warum sollte das passieren?
Ich verwende Kubuntu 18 und bash, falls das wichtig ist.
Akzeptierte Antwort:
Die GNU-Implementierung von uniq
wie auf Ubuntu gefunden, mit -c
, meldet keine Anzahl zusammenhängender identischer Zeilen, aber Anzahl zusammenhängender Zeilen, die gleich sortiert sind¹.
Die meisten internationalen Gebietsschemas auf GNU-Systemen haben diesen Fehler, dass viele völlig unabhängige Zeichen mit der gleichen Sortierreihenfolge definiert wurden, die meisten von ihnen, weil ihre Sortierreihenfolge überhaupt nicht definiert ist. Die meisten anderen Betriebssysteme stellen sicher, dass alle Zeichen eine andere Sortierreihenfolge haben.
$ expr ܐ = ܒ
1
(expr
ist =
-Operator gibt für Argumente, die nicht numerisch sind, 1 zurück, wenn die Operanden gleich sortiert sind, sonst 0).
Dasselbe gilt für ar_SY.UTF-8
oder en_GB.UTF-8
.
Was Sie brauchen, ist ein Gebietsschema, in dem diese Zeichen eine andere Sortierreihenfolge erhalten haben. Wenn Ubuntu Gebietsschemas für die syrische Sprache hätte, könnten Sie erwarten, dass diese Zeichen eine andere Sortierreihenfolge erhalten hätten, aber Ubuntu hat keine solchen Gebietsschemas.
Sie können sich die Ausgabe von locale -a
ansehen für eine Liste der unterstützten Gebietsschemas. Sie können weitere Gebietsschemata aktivieren, indem Sie dpkg-reconfigure locales
ausführen als root
. Sie können mit localedef
auch manuell weitere Locales definieren basierend auf den Definitionsdateien in /usr/share/i18n/locales
, aber Sie finden dort keine Daten für die syrische Sprache.
Beachten Sie das in:
LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c
Sie setzen nur die Variable LC_COLLATE für cat
Befehl (der keinen Einfluss darauf hat, wie er den Inhalt der Datei cat
ausgibt kümmert sich nicht um die Sortierung oder sogar die Zeichencodierung, da es kein Textdienstprogramm ist). Sie möchten es für beide sort
festlegen und uniq
. Sie möchten auch LC_CTYPE
festlegen zu einem Gebietsschema, das einen UTF-8-Zeichensatz hat.
Da Ihr System nicht über syr_SY.utf8
verfügt Gebietsschema, das ist dasselbe wie die Verwendung von C
Gebietsschema (das Standardgebietsschema).
Hier ist wahrscheinlich das Gebietsschema C oder C.UTF-8 das Gebietsschema, das Sie verwenden möchten.
In diesen Gebietsschemata basiert die Kollatierungsreihenfolge auf Codepunkt, Unicode-Codepunkt für C.UTF-8, Bytewert für C, aber das ist am Ende dasselbe wie die UTF-8-Zeichenkodierung diese Eigenschaft hat.
$ LC_ALL=C expr ܐ = ܒ
0
$ LC_ALL=C.UTF-8 expr ܐ = ܒ
0
Also mit:
(export LANG=ar_SY.UTF-8 LC_COLLATE=C.UTF-8 LANGUAGE=syr:ar:en
unset LC_ALL
sort <file | uniq -c)
Sie hätten einen LC_CTYPE mit UTF-8 als Zeichensatz, eine Sortierreihenfolge basierend auf dem Codepunkt und die anderen Einstellungen, die für Ihre Region relevant sind, also zum Beispiel Fehlermeldungen in Syrisch oder Arabisch, wenn GNU Coreutils sort
oder uniq
Nachrichten wurden in diese Sprachen übersetzt (noch nicht).
Wenn Ihnen diese anderen egal sind Einstellungen, es ist genauso einfach (und auch portabler) zu verwenden:
<file LC_ALL=C sort | LC_ALL=C uniq -c
Oder
(export LC_ALL=C; <file sort | uniq -c)
wie @isaac bereits gezeigt hat.