Как избежать изменения формата файла Sed?

Как избежать изменения формата файла Sed?

Я пытался использовать файл sed для предварительной обработки файла, но вывод sed, похоже, меняет формат. Как этого избежать?

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

Поскольку B.txt не закодирован в UTF-8, я не могу выполнить следующую обработку.

vim B.txt
è·¯æ<98><93>æ<96>¯ Âç½<97>å¾·é<87><8c>æ ¼æ<96>¯ //è·¯æ<98><93>æ<96>¯Â·ç½<97>å¾·é<87><8c>æ ¼æ<96>¯ ]

решение1

Проблема в том, что движок регулярных выражений sed не видит ни ваш входной файл, ни ваше […]совпадение как список символов Unicode; вместо этого он видит каждый из них как несколько независимых байтов. Например, он видит как три байта \xe2 \x80 \xa2и пытается сопоставить каждый из них по отдельности с [ \xe2 \x80 \x98 \xe2 \x80 \x99 \x22 \xe2 \x80 ... ].

Итак, в примере, который вы показали в своем посте, регулярное выражение сопоставляет и удаляет только последний байт каждого символа пунктуации, но оставляет остальные 2 на месте. Это то, что дает вам недействительный (не-UTF-8) выходной файл.

С помощью GNU sed (проверено на 4.5) этого можно избежать, убедившись, чтосистемная локаль(переменные среды $LANG или, по крайней мере, $LC_CTYPE) установлены на локаль, совместимую с UTF-8. Например:

$ экспорт LANG='C'
$ echo ''тест' "тест"' | sed 's/[""•]/X/g'
XX�тестXX� XXXтестXXX
$ echo '•_test' | sed 's/[•‡]_/X_/'
��X_тест

$ экспорт LANG='en_US.UTF-8'
$ echo ''тест' "тест"' | sed 's/[""•]/X/g'
'тест' XtestX
$ echo '•_test' | sed 's/[•‡]_/X_/'
X_тест

(Язык региона не имеет значения.Любой(Язык UTF-8 будет работать.)

Если это вам не подходит, избегайте этого […]полностью и используйте \(…\|…\|…\)(или (…|…|…)в sed -r), что является альтернативой для нескольких символов и будет работать независимо от того, как эти символы будут интерпретированы.

$ экспорт LANG='C'
$ echo ''тест' "тест"' | sed 's/\("\|"\|•\)/X/g'
'тест' XtestX
$ echo '•_test' | sed 's/\(•\|‡\)_/X_/'
X_тест

Связанный контент