Ist LC_ALL=C destruktiv?

Ist LC_ALL=C destruktiv?

Ich habe einen ziemlich großen Satz (~15 GB) Textdateien. Diese Dateien sind im Wesentlichen einfache Datenbanken, die Anmeldeinformationen enthalten, und die darin enthaltenen Anmeldeinformationen liegen oft außerhalb des 128-stelligen ASCII-Bereichs (Akzentzeichen und dergleichen).

Wenn ich versuche, einige dieser Dateien mit folgendem zu sortieren:

sort -u input.txt -o output.txt

... erhalte ich die folgende Fehlermeldung:

sort: string comparison failed: Invalid or incomplete multibyte or wide character
sort: Set LC_ALL='C' to work around the problem.

Ich habe viel darüber gelesen, wie die Verwendung von Befehlen, die mit Zeichen arbeiten, wie und , LC_ALL=Cbeschleunigen kann , einschließlichsortgrepStephane Chazelas' brillante Antwortzu diesem Thema, aber ich mache mir insbesondere Sorgen über die Auswirkungen, die die Verwendung auf meinen Datensatz hat.

Ist es wahrscheinlich, dass beim Ausführen LC_ALL=C sort -udieser Dateien alle Nicht-ASCII-Zeichen entfernt werden?

Wenn es, was kann ich dann stattdessen tun, um alle "ungültige oder unvollständige Multibyte- oder Wide-Zeichen" aus diesen Dateien, sodass ich sie sortieren kann, ohne LC_ALL=C? zu verwenden.

Antwort1

Ist es wahrscheinlich, dass durch das Ausführen von LC_ALL=C sort -u auf diesen Dateien alle Nicht-ASCII-Zeichen entfernt werden?

In diesem Fall nicht. Nein – sortwir arbeiten direkt mit den Bytewerten, anstatt zu versuchen, sie in Zeichen umzuwandeln.

Das Gleiche gilt jedoch nicht unbedingt für andere Tools. Programme, die in C (der Sprache) geschrieben sind, verhalten sich am wahrscheinlichsten so. Programme, die in Sprachen mit starker Unterscheidung zwischen Byte und Zeichen geschrieben sind, wie etwa Python 3, sollten Eingaben, die nicht dem Zeichensatz entsprechen, grundsätzlich ablehnen. Und ich kann mir durchaus schlecht geschriebene Programme vorstellen, die die Fehler ignorieren und ?stattdessen ein � oder a ausgeben.

Wenn ja, was kann ich stattdessen tun, um alle „ungültigen oder unvollständigen Multibyte- oder Breitzeichen“ aus diesen Dateien zu korrigieren/entfernen, sodass ich sie sortieren kann, ohne LC_ALL=C zu verwenden?

Stellen Sie sicher, dass alle die gleiche Dateikodierung verwenden (vorzugsweise UTF-8) und dass Ihr Gebietsschema die gleiche Kodierung verwendet. Der Fehler sollte bei einer gültigen UTF-8-Datei nie auftreten, egal wie groß sie ist.

Antwort2

Da ich meine Dateien letztendlich durch viele verschiedene Bash-Tools wie sort, grep, awk, wcund leiten musste tr, entschied ich mich für die sicherere „richtige Lösung“, die in der akzeptierten Antwort angegeben war, nämlich sie alle zuerst in UTF-8 umzuwandeln. Das war letztendlich etwas schwieriger als erwartet, nicht zuletzt, weil ich eine Weile brauchte, um zu erkennen, dass filenicht zuverlässig bestimmt werden kann, ob eine Datei ASCII oder UTF-8 ist (weil nicht die gesamte Datei überprüft wird), also stelle ich diese Antwort hier für die Nachwelt ein.

Um definitiv zu bestimmen, in welcher Kodierung Ihre Dateien vorliegen, stellen Sie zunächst sicher, dass das uchardetPaket über den Cygwin-Installer installiert wurde oderapt-cyg, dann renne:

uchardet *.txt

Oder wenn Sie Cygwin nicht verwenden:

chardet *.txt 

chardetVerschieben Sie alle aufgelisteten Dateien ASCIIin einen eigenen Ordner und führen Sie forin diesem Ordner die folgende Schleife aus:

for i in *.txt; do iconv -f ASCII -t UTF-8 "$i" >> "${i%.txt}_utf.txt"; done;

Es durchläuft alle .txtDateien in einem Ordner und erstellt davon UTF-8-Versionen mit utfhinzugefügtem Suffix.

Beim erneuten Ausführen uchardet *.txtwerden möglicherweise immer noch einige Dateien als angezeigt ASCII. Dies liegt daran, dass ASCII eine Teilmenge von UTF-8 ist undbedeutet einfachdass diese Dateien keine Zeichen außerhalb des 128-Bit-ASCII-Bereichs enthalten.

Jetzt sollten Sie in der Lage sein, auszuführen, sortohne verwenden zu müssen LC_ALL=C.

verwandte Informationen