Como evitar que o Sed altere o formato do arquivo?

Como evitar que o Sed altere o formato do arquivo?

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

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 B.txt não está codificado em UTF-8, não posso fazer o processamento seguinte.

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

Responder1

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

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

Com o GNU sed (testado em 4.5), isso pode ser evitado certificando-se de que olocalidade do sistema(as variáveis ​​de ambiente $LANG ou pelo menos $LC_CTYPE) estão definidas para um código de idioma compatível com UTF-8. Por exemplo:

$ exportar LANG='C'
$ echo ''teste' “teste”' | sed 's/[“”•]/X/g'
XX�testeXX� XXXtesteXXX
$ echo '•_test' | sed 's/[•‡]_/X_/'
��X_teste

$ exportar LANG='en_US.UTF-8'
$ echo ''teste' “teste”' | sed 's/[“”•]/X/g'
'teste' XtestX
$ echo '•_test' | sed 's/[•‡]_/X_/'
X_teste

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

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

$ exportar LANG='C'
$ echo ''teste' “teste”' | sed 's/\(“\|”\|•\)/X/g'
'teste' XtestX
$ echo '•_test' | sed 's/\(•\|‡\)_/X_/'
X_teste

informação relacionada