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

332
Luca

Я пытался использовать файл 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>¯ ] 
0
Я не думаю, что sed поддерживает Unicode ... что вы пытаетесь сделать? (пожалуйста, включите полное содержание `process.sed`) Attie 5 лет назад 0
Какие переменные окружения `LC_ALL` /` LANG` / `LANGUAGE` установлены в? Attie 5 лет назад 1
@ Atttie Я пытаюсь удалить все китайские знаки препинания с тегами. Luca 5 лет назад 0
@ Attike like '' Это pun 、 / DunHao "->" Это punc ". Но удаляйте только пунктуацию с тегами Luca 5 лет назад 0

1 ответ на вопрос

1
grawity

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

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

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

$ export LANG = 'C' $ echo '' test '“test”' | sed 's / [“” •] / X / g' XX testXX XXXtestXXX $ echo '• _test' | sed 's / [• ‡] _ / X_ /' X_test  $ export LANG = 'en_US.UTF-8' $ echo '' test '“test”' | sed 's / [“” •] / X / g' «тест» XtestX $ echo '• _test' | sed 's / [• ‡] _ / X_ /' X_test 

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

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

$ export LANG = 'C' $ echo '' test '“test”' | sed 's / \ (“\ |” \ | • \) / X / g' «тест» XtestX $ echo '• _test' | sed 's / \ (• \ | ‡ \) _ / X_ /' X_test 

Похожие вопросы