¿Cómo reemplazar todas las subcadenas UTF-8 codificadas por porcentaje con texto UTF-8 simple?

9

Tengo un archivo html con mucho texto UTF-8 codificado en% en las URL.

Por ejemplo, "% D1% 80% D0% B5% D1% 81% D1% 83% D1% 80% D1% 81% D1% 8B" significa "ресурсы" ("recursos" en ruso).

La tarea es reemplazar todas esas subcadenas con texto legible UTF-8.

Para simplificar la tarea, podemos considerar que no hay otro %uso de signos en el archivo. Los dígitos de las letras pueden ser mayúsculas y minúsculas.

Sospecho que esto se puede hacer con elegancia sed, perl, awko algo, pero no saben cómo.

Esta aplicación web parece hacer el truco con el texto que pegas allí.

Ivan
fuente

Respuestas:

9

Con bash, zsh, GNU echo o algunas implementaciones de ksh en algunos sistemas, esto puede decodificarse simplemente echo -ereemplazando todo %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: ресурсы

(Se supone que la cadena en sí no contiene caracteres de barra invertida y no es una de las opciones admitidas por su echocomando)

Como @JoshLee también señala, la "advertencia de eco" se puede evitar usando directamente:

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

en cambio directamente detrás del primer comando.

LiuYan 刘 研
fuente
Tenga en cuenta que esta elegante solución funcionará con cualquier codificación, no solo con UTF-8 (es decir, elimine las codificaciones para ~ y otros. Otro truco para agregar a mi caja de herramientas. ¡Gracias!
vonbrand
5

Con perl:

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

O con URI::Escape:

perl -MURI::Escape -pe '$_=uri_unescape$_'
Stéphane Chazelas
fuente
Me encanta esto porque puedo canalizar lo que quiera gracias a $_ gnu.org/software/bash/manual/html_node/Special-Parameters.html
Nemo
@Nemo, $_aquí hay perl's $_, no bash' s. En combinación con la -popción, la expresión perl se ejecuta para cada registro de entrada (los registros se leen de los archivos dados como argumento o stdin si no se proporciona ningún argumento), con el registro actual almacenado $_. Eso es similar a awk's $0.
Stéphane Chazelas
0

Hay un programa llamado convmvque puede ayudarlo.

Simplemente use convmv --unescape /some_path/target_file. Hará una carrera en seco.

Una vez que haya confirmado, use convmv --notest --unescape /some_path/target_filepara continuar.

La página de inicio de este programa es: http://j3e.de/linux/convmv/

Estrella brillante
fuente