
Я пытался использовать файл 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_тест