Como substituir todas as substrings UTF-8 codificadas por porcentagem por texto UTF-8 simples?

9

Eu tenho um arquivo html com muito texto UTF-8 codificado em% em URLs.

Por exemplo, "% D1% 80% D0% B5% D1% 81% D1% 83% D1% 80% D1% 81% D1% 8B" significa "ресурсы" ("recursos" em russo).

A tarefa é substituir todas essas substrings por texto UTF-8 legível.

Para simplificar a tarefa, podemos considerar que não há outro %uso de sinal no arquivo. Os dígitos das letras podem ser maiúsculas e minúsculas.

Eu suspeito que isso pode ser feito de forma elegante com sed, perl, awkou algo assim, mas não sei como.

Esse aplicativo da Web parece funcionar com o texto que você cola lá.

Ivan
fonte

Respostas:

9

Com bash, zsh, GNU echo ou algumas implementações do ksh em alguns sistemas, isso pode ser decodificado simplesmente echo -eapós a substituição de todos %por \x.

url_encoded_string="%D1%80%D0%B5%D1%81%D1%83%D1%80%D1%81%D1%8B"
temp_string=${url_encoded_string//%/\\x}

printf '%s\n' "$temp_string"
# output: \xD1\x80\xD0\xB5\xD1\x81\xD1\x83\xD1\x80\xD1\x81\xD1\x8B

echo -e "$temp_string"
# output: ресурсы

(Ele assume que a própria string não contém caracteres de barra invertida e não é uma das opções suportadas pelo seu echocomando)

Como o @JoshLee também aponta, a "advertência de eco" pode ser evitada usando diretamente:

printf ${url_encoded_string//%/\\x}

em vez diretamente atrás do primeiro comando.

LiuYan 刘 研
fonte
Note-se que esta solução elegante irá trabalhar com qualquer . Codificação, não apenas UTF-8 (ou seja, livrar-se das codificações para ~ e outros Outro truque para adicionar à minha caixa de ferramentas Graças.!
vonbrand
5

Com perl:

perl -pe 's/%([0-9A-F]{2})/pack"H2",$1/gei'

Ou com URI::Escape:

perl -MURI::Escape -pe '$_=uri_unescape$_'
Stéphane Chazelas
fonte
Eu amo isso porque eu pode canalizar isso o que eu quiser, graças a $_ gnu.org/software/bash/manual/html_node/Special-Parameters.html
Nemo
@Nemo, $_aqui é perl's $_, não bash' s. Em combinação com a -popção, a expressão perl é executada para cada registro de entrada (registros sendo lidos a partir de arquivos fornecidos como argumento ou stdin se nenhum argumento for fornecido), com o registro atual armazenado em $_. Isso é semelhante ao awkda $0.
Stéphane Chazelas
0

Existe um programa chamado convmvque pode ajudá-lo.

Basta usar convmv --unescape /some_path/target_file. Ele fará um teste a seco.

Depois de confirmar, use convmv --notest --unescape /some_path/target_filepara continuar.

A página inicial deste programa é: http://j3e.de/linux/convmv/

Star Brilliant
fonte