staging.inyokaproject.org

cat und grep um iso-8859-15-dummydata zu erstellen

Status: Ungelöst | Ubuntu-Version: Kubuntu 16.04 (Xenial Xerus)
Antworten |

herrmeier

Anmeldungsdatum:
5. Oktober 2006

Beiträge: 297

Ich muss für ein paar Entwickler dummydata erstellen... Die Quell-Datei ist 370MB groß und hat einen Zeichensatz von iso-8859-15.

cat und grep alleine halten sie für eine binary-Datei. Dennoch benötige ich einige Zeilen aus der Datei um eine dummydata-zieldatei zu erstellen.

Meine Idee war folgende: cat Quelldatei.TXT |grep -a --text 'string1' > /pfad/zu/dummdata_zieldatei.TXT cat Quelldatei.TXT |grep -a --text 'string2' >> /pfad/zu/dummdata_zieldatei.TXT cat Quelldatei.TXT |grep -a --text 'string3' >> /pfad/zu/dummdata_zieldatei.TXT Die neue Datei ist allerdings UTF-8 und Umlaute und Sonderzeichen werden nicht richtig wiedergegeben.

Habt Ihr vielleicht eine Idee? Vielen Dank für Eure Hilfe!

Hans

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Standardprogramme wie cat oder grep orientieren sich an der Umgebung, und die heißt bei den hier üblichen *nix-Systemen "utf-8".

Also liefern alle Zeichen, die in diesem Zeichensatz nicht zugelassen sind, Fehler.
Abhilfe: für das Programm wird der Universal-Zeichensatz "C" in der Umgebung eingestellt:

1
LANG=C grep '# ...'  meine_giftige_quelldatei.ISO-8859-15.txt  >  meine_gifige_dummydatei.ISO-8859-15.txt

Damit sollte das Problem behoben sein.
(in dem Fall müsstest Du allerdings ggf. Sonderzeichen im Suchstring als deren ISO-8859-15 Binär-Äquivalent angeben.)

LG,

track

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

herrmeier schrieb:

Habt Ihr vielleicht eine Idee?

Die Datei unter Berücksichtigung des Encoding verarbeiten:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/usr/bin/env python3
from functools import partial

mystrings = ('string1', 'string2', 'string3') # select lines containing any of those strings
source_file='quelldatei.ISO-8859-15.txt'      # file to read from
target_file='dummydatei.ISO-8859-15.txt'      # file to write to

open2 = partial(open, encoding='iso-8859-15')
with open2(source_file, 'r') as origin, open2(target_file, 'w') as target:
    for line in origin:
        if any((True for s in mystrings if s in line)):
            target.write(line)

kB Team-Icon

Supporter, Wikiteam
Avatar von kB

Anmeldungsdatum:
4. Oktober 2007

Beiträge: 9837

Die Konvertierung der Zeichendarstellung leistet unter allen POSIX-kompatiblen Betriebssystemen, also auch linux, die iconv-Bibliothek. Diese ist aus allen maßgeblichen Programmiersprachen und natürlich auch direkt auf der Kommandozeile verwendbar:

man iconv

iconv -f ISO-8859-15 -t utf-8 Quelldatei-8859-15 > Quelldatei-utf-8    # übersetzt Deine 8859-59-Datei in eine utf-8-Version
grep -E 'string1|string2|string3' Quelldatei-utf-8 > Auszug-utf-8      # erstellt den gewünschten Auszug mit den Strings string1, string2 und string3
iconv -f utf-8 -t ISO-8859-15 Auszug-utf-8 > Auszug-8859-15            # übersetzt den Auszug nach 8859-15

Zur Behandlung von nicht übersetzbaren Zeichen siehe das Manual.

Du kannst natürlich die 3 Befehle auch in einer pipe benutzen. Wegen der beachtlichen Größe der Quelldatei würde ich das i.d.F nicht machen.

Möglicherweise musst Du noch die Zeilenenden separat auf die gewünschte Form (LF, CR, oder CRLF) bringen.

herrmeier

(Themenstarter)

Anmeldungsdatum:
5. Oktober 2006

Beiträge: 297

vielen Dank für Eure Hilfsbereitschaft! Ich probiere alles hintereinander aus. Zunächst von fern zu nah:

kb: Dort stoße ich dann wieder auf die Fehlermeldung: Übereinstimmungen in Binärdatei Meine Lösung wäre grep -a --text 'string1|string2|string3' Quelldatei-utf-8 > Auszug-utf-8

Allerdings bestehen string1 -strinX aus "Vorname, Nachname", insofern habe ich es manuell machen müssen? Wie würde ich die regexp denn richtig einbauen?

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

kB schrieb:

Die Konvertierung der Zeichendarstellung ...

Klar ist das möglich, aber doch ziemlich umständlich, finde ich.

Da wäre es ja fast einfacher, sich das komplette Environment für den ISO-8859-15 Zeichensatz nachzuladen, wie es hier beschrieben ist.
(also praktisch: die 1 Zeile in die /var/lib/locales/supported.d/de nachtragen, und dann dpkg-reconfigure locales ausführen)

Du kannst natürlich die 3 Befehle auch in einer pipe benutzen. Wegen der beachtlichen Größe der Quelldatei würde ich das i.d.F nicht machen.

Ist auch kein Problem, denn so eine Pipe speichert immer nur ±64 kByte zwischen, und lässt ggf. einen der beteiligten Prozesse warten, bis wieder genug Platz ist.

Möglicherweise musst Du noch die Zeilenenden separat auf die gewünschte Form (LF, CR, oder CRLF) bringen.

Auch kein Problem. Ein überschüssiges "\r" wird einfach als zusätzliches Zeichen hinten an der Zeile weiter gereicht - solange man nicht das Zeilenende abschneidet.

LG,

track

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

kB schrieb:

Du kannst natürlich die 3 Befehle auch in einer pipe benutzen. Wegen der beachtlichen Größe der Quelldatei würde ich das i.d.F nicht machen.

Gerade bei der Größe ist das ein Vorteil, weil man nämlich nicht erst die Daten auf Platte schreiben muss (Platz und Geschwindigkeit).

kB Team-Icon

Supporter, Wikiteam
Avatar von kB

Anmeldungsdatum:
4. Oktober 2007

Beiträge: 9837

herrmeier schrieb:

[…] kb: Dort stoße ich dann wieder auf die Fehlermeldung: Übereinstimmungen in Binärdatei Meine Lösung wäre grep -a --text 'string1|string2|string3' Quelldatei-utf-8 > Auszug-utf-8

  • Wenn Du grep mit der Option -a (--text ist dazu ein Alias) zwingst, die Textdatei als Binärdatei zu verstehen, meldet er natürlich „Übereinstimmungen in Binärdatei“. Lass diese Optionen einfach weg. Die von Dir vergessene Option -E ist wesentlich.

Allerdings bestehen string1 -strinX aus "Vorname, Nachname", insofern habe ich es manuell machen müssen? Wie würde ich die regexp denn richtig einbauen?

  • z.B.

    grep -E 'Mustermann, Erika|Niemand, Karl|Kaiser, Otto' Quelldatei > Auszug

kB Team-Icon

Supporter, Wikiteam
Avatar von kB

Anmeldungsdatum:
4. Oktober 2007

Beiträge: 9837

track schrieb:

kB schrieb:

Die Konvertierung der Zeichendarstellung ...

Klar ist das möglich, aber doch ziemlich umständlich, finde ich.

  • Was ist denn am immer und überall in der Unix-Welt installierten Standard iconv umständlich? Einfach anwenden: Übersetzen, filtern, zurück-übersetzen. Fertig.

Da wäre es ja fast einfacher, sich das komplette Environment für den ISO-8859-15 Zeichensatz nachzuladen, wie es hier beschrieben ist.
(also praktisch: die 1 Zeile in die /var/lib/locales/supported.d/de nachtragen, und dann dpkg-reconfigure locales ausführen)

  • Das finde ich umständlich und bedenklich! Zur Lösung einer Datei-Bearbeitung das eigene System umkonfigurieren? Das würde ich auf keinen Fall machen!

.

Seebär

Avatar von Seebär

Anmeldungsdatum:
2. Mai 2009

Beiträge: 833

kB schrieb:

  • Was ist denn am immer und überall in der Unix-Welt installierten Standard iconv umständlich?

Absolut nichts. Du hast vollkommen recht.

@track Wenn man unterschiedliche Zeichensätze hat, dann muss man damit sauber umgehen. Das macht nicht Spaß, ist oft mit Fehlern behaftet, ist u.U. auch aufwändig (aber nicht wg. iconv). Wichtig ist aber der saubere Umgang, und mit iconv hat man ein gutes Tool zur Hand, das auch sehr viele Zeichensätze unterstützt. Auch das Thema CRLF vs. LF ist nicht zu unterschätzen, hier sind dos2unix / unix2dos dein Freund. Habe durchaus schon Dateien gehabt, die in sich mal LF, mal CRLF hatten.

Das Encoding der Maschine umzustellen ist für mich eher ein no-go, da Du im Regelfall a) die Folgen nicht überblickst und b) damit nichts löst. Das kann man bestenfalls bei der Installation bewusst anders entscheiden, ich würde aber den Linux-Default UTF8 belassen, und keine Sonderlocken verwenden.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Seebär schrieb:

Das Encoding der Maschine umzustellen

Das hat track nicht vorgeschlagen. Es ging nur darum, fehlende Locales zu installieren um sie dann temporär (für ein Kommando) nutzen zu können.

ist für mich eher ein no-go, da Du im Regelfall a) die Folgen nicht überblickst und b) damit nichts löst. Das kann man bestenfalls bei der Installation bewusst anders entscheiden, ich würde aber den Linux-Default UTF8 belassen, und keine Sonderlocken verwenden.

Ja, aber s.o.

Bearbeitet von sebix:

Userlink repariert.

Antworten |