bash shell awk sed urldecode

bash - Cómo decodificar cadena codificada en URL en shell?



awk sed (17)

Aquí hay una solución que se hace en pure bash donde input y output son variables bash. Descodificará ''+'' como un espacio y manejará el espacio ''% 20'', así como otros caracteres codificados en%.

#!/bin/bash #here is text that contains both ''+'' for spaces and a %20 text="hello+space+1%202" decoded=$(echo -e `echo $text | sed ''s/+/ /g;s/%/////x/g;''`) echo decoded=$decoded

Tengo un archivo con una lista de usuarios-agentes que están codificados. P.ej:

Mozilla%2F5.0%20%28Macintosh%3B%20U%3B%20Intel%20Mac%20OS%20X%2010.6%3B%20en

Quiero un script de shell que pueda leer este archivo y escribir en un nuevo archivo con cadenas decodificadas.

Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en

He intentado utilizar este ejemplo para ponerlo en funcionamiento, pero hasta ahora no ha funcionado.

$ echo -e "$(echo "%31+%32%0A%33+%34" | sed ''y/+/ /; s/%///x/g'')"

Mi script se ve así:

#!/bin/bash for f in *.log; do echo -e "$(cat $f | sed ''y/+/ /; s/%//x/g'')" > y.log done


Aquí hay una solución simple de una línea.

$ urldecode() { : "${*//+/ }"; echo -e "${_//%///x}"; }

Puede parecer perl :) pero es pura bash. No awks, no seds ... no overheads. Usando el: built-in, parámetros especiales, sustitución de patrones y la opción -e incorporada del eco para traducir códigos hexadecimales en caracteres. Ver la página de manual de bash para más detalles. Puede usar esta función como comando separado

$ urldecode https%3A%2F%2Fgoogle.com%2Fsearch%3Fq%3Durldecode%2Bbash https://google.com/search?q=urldecode+bash

o en asignaciones variables, así:

$ x="http%3A%2F%2F.com%2Fsearch%3Fq%3Durldecode%2Bbash" $ y=$(urldecode "$x") $ echo "$y" http://.com/search?q=urldecode+bash


Awk de GNU

#!/usr/bin/awk -fn @include "ord" BEGIN { RS = "%.." } { printf RT ? $0 chr("0x" substr(RT, 2)) : $0 }

O

#!/bin/sh awk -niord ''{printf RT?$0chr("0x"substr(RT,2)):$0}'' RS=%..

Uso de awk printf para urldecode text


Como dijo barti_ddu en los comentarios, /x "debería ser [doble]" escapado ".

% echo -e "$(echo "Mozilla%2F5.0%20%28Macintosh%3B%20U%3B%20Intel%20Mac%20OS%20X%2010.6%3B%20en" | sed ''y/+/ /; s/%///x/g'')" Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en

En lugar de mezclar Bash y sed, haría todo esto en Python. Aquí hay un corte aproximado de cómo:

#!/usr/bin/env python import glob import os import urllib for logfile in glob.glob(os.path.join(''.'', ''*.log'')): with open(logfile) as current: new_log_filename = logfile + ''.new'' with open(new_log_filename, ''w'') as new_log_file: for url in current: unquoted = urllib.unquote(url.strip()) new_log_file.write(unquoted + ''/n'')


Con BASH, para leer el porcentaje de URL codificada de estándar en y decodificar:

while read; do echo -e ${REPLY//%///x}; done

Presione CTRL - D para señalar el final del archivo (EOF) y salga con elegancia.

Puede decodificar el contenido de un archivo configurando el archivo para que sea estándar en:

while read; do echo -e ${REPLY//%///x}; done < file

También puede decodificar la entrada desde un conducto, por ejemplo:

echo ''a%21b'' | while read; do echo -e ${REPLY//%///x}; done

  • El comando de lectura integrada lee estándar hasta que ve un carácter de alimentación de línea. Establece una variable llamada REPLY igual a la línea de texto que acaba de leer.
  • ${REPLY//%///x} reemplaza todas las instancias de ''%'' con ''/ x''.
  • echo -e interpreta /xNN como el carácter ASCII con valor hexadecimal de NN .
  • mientras repite este bucle hasta que falla el comando de lectura, ej. EOF ha sido alcanzado.

Esto no cambia ''+'' a ''''. Eso se puede agregar como en la answer del invitado. Esto solo usa BASH y no inicia ningún otro proceso, similar a la respuesta del invitado.


Con GNU awk :

gawk -vRS=''%[0-9a-fA-F]{2}'' ''RT{sub("%","0x",RT);RT=sprintf("%c",strtonum(RT))} {gsub(//+/," ");printf "%s", $0 RT}''


Enfrentando un problema similar, mi idea inicial era usar urldecode de PHP en un script que lee stdin o algo así, pero luego me encontré con esta idea. Todas las respuestas parecen tener mucho texto, pero no presentan una solución real. La idea es sólida e increíblemente fácil de usar:

$ mpc | sed -e ''1! d'' http://e.org/play.php?name=/Black%20Sun%20Empire%20-%20Sideways%20%28Feat.%20Illy%20Emcee%29 $ basename "$(echo -e `mpc | sed -e ''1! d'' -e ''s/%/////x/g''`)" Black Sun Empire - Sideways (Feat. Illy Emcee)

La clave para hacer que funcione es el doble escape / x (esto ya se ha mencionado).


Esto es lo que parece estar funcionando para mí.

#!/bin/bash urldecode(){ echo -e "$(sed ''s/+/ /g;s/%/(../)///x/1/g;'')" } for f in /opt/logs/*.log; do name=${f##/*/} cat $f | urldecode > /opt/logs/processed/$HOSTNAME.$name done

Reemplazar ''+'' s con espacios, y% signos con ''/ x'' escapes, y dejar que echo interprete los / x escapes usando la opción ''-e'' no funcionaba. Por alguna razón, el comando cat estaba imprimiendo el signo% como su propia forma codificada% 25. Entonces sed simplemente estaba reemplazando% 25 con / x25. Cuando se usaba la opción -e, simplemente evaluaba / x25 como% y el resultado era el mismo que el original.

Rastro:

Original: Mozilla% 2F5.0% 20% 28Macintosh% 3B% 20U% 3B% 20Intel% 20Mac% 20OS% 20X% 2010.6% 3B% 20en

sed: Mozilla / x252F5.0 / x2520 / x2528Macintosh / x253B / x2520U / x253B / x2520Intel / x2520Mac / x2520OS / x2520X / x252010.6 / x253B / x2520en

echo -e: Mozilla% 2F5.0% 20% 28Macintosh% 3B% 20U% 3B% 20Intel% 20Mac% 20OS% 20X% 2010.6% 3B% 20en

Solución: Básicamente ignore los 2 caracteres después del% en sed.

sed: Mozilla / x2F5.0 / x20 / x28Macintosh / x3B / x20U / x3B / x20Intel / x20Mac / x20OS / x20X / x2010.6 / x3B / x20en

echo -e: Mozilla / 5.0 (Macintosh; U; Intel Mac OS X 10.6;

No estoy seguro de qué complicaciones resultaría, después de pruebas extensas, pero funciona por ahora.


Expandiendo a https://.com/a/37840948/8142470
para trabajar con entidades HTML

$ htmldecode () {: "$ {* // + /}"; echo -e "$ {_ // & # x / / x}" | tr -d '';''; }
$ htmldecode "http & # x3A; & # x2F; & # x2F; google.com & # x2F; búsqueda && # x3F; q & # x3D; urldecode & # x2B; bash" http://google.com/search&?q=urldecode+bash

(el argumento debe ser citado)


Script Bash para hacerlo en nativo Bash ( fuente original ):

LANG=C urlencode() { local l=${#1} for (( i = 0 ; i < l ; i++ )); do local c=${1:i:1} case "$c" in [a-zA-Z0-9.~_-]) printf "$c" ;; '' '') printf + ;; *) printf ''%%%.2X'' "''$c" esac done } urldecode() { local data=${1//+/ } printf ''%b'' "${data//%//x}" }

Si desea urldecode contenido de archivo, simplemente ponga el contenido del archivo como argumento.

Aquí hay una prueba que se detendrá si el contenido codificado del archivo decodificado difiere (si se ejecuta durante unos segundos, la secuencia de comandos probablemente funcione correctamente):

while true do cat /dev/urandom | tr -d ''/0'' | head -c1000 > /tmp/tmp; A="$(cat /tmp/tmp; printf x)" A=${A%x} A=$(urlencode "$A") urldecode "$A" > /tmp/tmp2 cmp /tmp/tmp /tmp/tmp2 if [ $? != 0 ] then break fi done


Si tiene instalado php en su servidor, puede "cat" o incluso "rastrear" cualquier archivo, con cadenas codificadas en url muy fácilmente.

tail -f nginx.access.log | php -R ''echo urldecode($argn)."/n";''


Solo quería compartir esta otra solución, pure bash:

encoded_string="Mozilla%2F5.0%20%28Macintosh%3B%20U%3B%20Intel%20Mac%20OS%20X%2010.6%3B%20en" printf -v encoded_string "%b" "${encoded_string///%//x}" echo $encoded_string


Una versión ligeramente modificada de la respuesta de Python que acepta un archivo de entrada y salida en un solo liner.

cat inputfile.txt | python -c "import sys, urllib as ul; print ul.unquote(sys.stdin.read());" > ouputfile.txt


si eres un desarrollador de Python , esto quizás prefiera

echo "%21%20" | python -c "import sys, urllib as ul; print ul.unquote(sys.stdin.read());"

urllib es profesional en manejarlo


perl -pi.back -e ''y/+/ /;s/%([/da-f]{2})/pack H2,$1/gie'' ./*.log

Con -i actualiza los archivos in situ (algunas implementaciones sed han tomado prestado de perl ) con .back como la extensión de copia de seguridad.

s/x/y/e sustituye x con la valoración e del código y perl.

El código de perl en este caso usa un pack para empaquetar el número hexadecimal capturado en $1 (el primer par de paréntesis en la expresión regular) como el personaje correspondiente.

Una alternativa al pack es usar chr(hex($1)) :

perl -pi.back -e ''y/+/ /;s/%([/da-f]{2})/chr hex $1/gie'' ./*.log

Si está disponible, también puede usar uri_unescape() desde URI::Escape :

perl -pi.back -MURI::Escape -e ''y/+/ /;$_=uri_unescape$_'' ./*.log


$ uenc=''H%C3%B6he %C3%BCber%20dem%20Meeresspiegel'' $ utf8=$(echo -e "${uenc//%///x}") $ echo $utf8 Höhe über dem Meeresspiegel $


$ uenc=''H%C3%B6he %C3%BCber%20dem%20Meeresspiegel'' $ utf8=$(printf "${uenc//%///x}") $ echo $utf8 Höhe über dem Meeresspiegel $