Wie vermeide ich, dass Sed das Dateiformat ändert?

411
Luca

Ich habe versucht, eine sed-Datei zum Vorverarbeiten einer Datei zu verwenden, aber die Ausgabe von sed scheint das Format zu ändern. Wie soll ich das vermeiden?

file A.txt A.txt UTF-8 Unicode English text, with very long lines  sed -f process.sed < A.txt > B.txt  head -2 process.sed #!/bin/sed -f s/[‘’"“”•·・、。《》™®\.★☆]\\[a-z\-]\+ //g  file B.txt Non-ISO extended-ASCII English text, with very long lines, with LF, NEL line terminators 

Da B.txt nicht in UTF-8 codiert ist, kann ich die folgende Verarbeitung nicht durchführen.

vim B.txt è·¯æ<98><93>æ<96>¯ Âç½<97>å¾·é<87><8c>æ ¼æ<96>¯ //è·¯æ<98><93>æ<96>¯Â·ç½<97>å¾·é<87><8c>æ ¼æ<96>¯ ] 
0
Ich denke nicht, _dink_ `sed` unterstützt Unicode ... Was versuchen Sie zu tun? (Bitte geben Sie den vollständigen Inhalt von `process.sed` an.) Attie vor 5 Jahren 0
Was sind Ihre Umgebungsvariablen "LC_ALL" / "LANG" / "LANGUAGE"? Attie vor 5 Jahren 1
Ich versuche, alle chinesischen Satzzeichen mit Tags zu entfernen. Luca vor 5 Jahren 0
@Attie like '' Dies ist ein 、 / DunHao punc "->" Dies ist ein Punc ". Entfernen Sie jedoch nur Satzzeichen mit Tags Luca vor 5 Jahren 0

1 Antwort auf die Frage

1
grawity

Das Problem ist, dass die Regex-Engine von Sed weder Ihre Eingabedatei noch Ihre […]Übereinstimmung als eine Liste von Unicode-Zeichen sieht . Stattdessen sieht es jedes von ihnen als mehrere unabhängige Bytes. Beispielsweise sieht es drei Bytes \xe2 \x80 \xa2und versucht, jedes davon einzeln anzugleichen [ \xe2 \x80 \x98 \xe2 \x80 \x99 \x22 \xe2 \x80 ... ].

In dem Beispiel, das Sie in Ihrem Beitrag gezeigt haben, stimmt der Regex nur mit dem letzten Byte jedes Interpunktionszeichens überein und löscht es, aber die anderen 2 bleiben dort. Das gibt Ihnen eine ungültige (nicht UTF-8) Ausgabedatei.

Mit GNU sed (getestet auf 4.5) kann dies vermieden werden, indem sichergestellt wird, dass das Systemgebietsschema (Umgebungsvariablen $ LANG oder mindestens $ LC_CTYPE) auf ein UTF-8-kompatibles Gebietsschema gesetzt ist. Zum Beispiel:

$ export LANG = 'C' $ echo '' test '' test '' | sed 's / ["" •] / X / g' XX testXXtest XXXtestXXX $ echo '• _test' | sed 's / [• ‡] _ / X_ /' X_test  $ export LANG = 'de_US.UTF-8' $ echo '' test '' test '' | sed 's / ["" •] / X / g' 'test' XtestX $ echo '• _test' | sed 's / [• ‡] _ / X_ /' X_test 

(Die Sprache des Gebietsschemas spielt keine Rolle. Jedes UTF-8-Gebietsschema wird funktionieren.)

Wenn dies für Sie nicht funktioniert, vermeiden Sie […]vollständig und verwenden Sie \(…\|…\|…\)(oder (…|…|…)in sed -r). Dies ist eine Alternative mit mehreren Zeichen und funktioniert unabhängig davon, wie diese Zeichen interpretiert werden.

$ export LANG = 'C' $ echo '' test '' test '' | sed 's / \ ("\ |" \ | • \) / X / g' 'test' XtestX $ echo '• _test' | sed 's / \ (• \ | ‡ \) _ / X_ /' X_test