Como evitar que Sed altere o formato do arquivo?

0

Eu estava tentando usar um arquivo sed para pré-processar um arquivo, mas a saída do sed parece alterar o formato. Como devo evitar isso?

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

Como o arquivo B.txt não é codificado como UTF-8, não posso fazer o seguinte processamento.

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

1 resposta

1

O problema é que o mecanismo regexp do sed não vê seu arquivo de entrada nem sua […] corresponde a uma lista de caracteres Unicode; Em vez disso, ele vê cada um deles como vários bytes independentes. Por exemplo, ele vê como três bytes \xe2 \x80 \xa2 e tenta corresponder cada um deles individualmente com [ \xe2 \x80 \x98 \xe2 \x80 \x99 \x22 \xe2 \x80 ... ] .

Assim, no exemplo mostrado em sua postagem, o regex corresponde e exclui apenas o último byte de cada caractere de pontuação, mas deixa os outros 2 ainda presentes. Isso é o que dá a você um arquivo de saída inválido (não-UTF-8).

Com o GNU sed (testado no 4.5), isso pode ser evitado certificando-se de que o system locale (as variáveis de ambiente $ LANG ou pelo menos $ LC_CTYPE) esteja configurado para um compatível com UTF-8 localidade. Por exemplo:

$ 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'
‘test’ XtestX
$ echo '•_test' | sed 's/[•‡]_/X_/'
X_test

(O idioma local não importa. Qualquer localidade UTF-8 funcionará.)

Se isso não funcionar para você, evite […] completamente e use \(…\|…\|…\) (ou (…|…|…) in sed -r), que é uma alternativa de vários caracteres e funcionará independentemente de como esses caracteres acabam sendo interpretado.

$ export LANG='C'
$ echo '‘test’ “test”' | sed 's/\(“\|”\|•\)/X/g'
‘test’ XtestX
$ echo '•_test' | sed 's/\(•\|‡\)_/X_/'
X_test
    
por 10.08.2018 / 11:48