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
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
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: | 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: 11176
Wohnort: München
|
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
Supporter, Wikiteam
Anmeldungsdatum: 4. Oktober 2007
Beiträge: 8558
Wohnort: Münster
|
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
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
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
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12801
|
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
Supporter, Wikiteam
Anmeldungsdatum: 4. Oktober 2007
Beiträge: 8558
Wohnort: Münster
|
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?
|
kB
Supporter, Wikiteam
Anmeldungsdatum: 4. Oktober 2007
Beiträge: 8558
Wohnort: Münster
|
track schrieb: 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)
.
|
Seebär
Anmeldungsdatum: 2. Mai 2009
Beiträge: 829
|
kB schrieb: 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
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12801
|
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.
|