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 \xa2
und 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