解码URL编码(百分比编码)

Dis*_*ame 132 url sed shell-script text-processing

我想解码 URL 编码,是否有任何内置工具可以执行此操作,或者谁能为我提供sed可以执行此操作的代码?

我确实通过unix.stackexchange.com和互联网进行了一些搜索,但我找不到任何用于解码 url 编码的命令行工具。

我想要做的只是就地编辑txt文件,以便:

  • %21 变成 !
  • %23 变成 #
  • %24 变成 $
  • %26 变成 &
  • %27 变成 '
  • %28 变成 (
  • %29 变成 )

等等。

slm*_*slm 157

发现这些 Python one 衬垫可以满足您的需求:

蟒蛇2

$ alias urldecode='python -c "import sys, urllib as ul; \
    print ul.unquote_plus(sys.argv[1])"'

$ alias urlencode='python -c "import sys, urllib as ul; \
    print ul.quote_plus(sys.argv[1])"'
Run Code Online (Sandbox Code Playgroud)

蟒蛇3

$ alias urldecode='python3 -c "import sys, urllib.parse as ul; \
    print(ul.unquote_plus(sys.argv[1]))"'

$ alias urlencode='python3 -c "import sys, urllib.parse as ul; \
    print (ul.quote_plus(sys.argv[1]))"'
Run Code Online (Sandbox Code Playgroud)

例子

$ urldecode 'q+werty%3D%2F%3B'
q werty=/;

$ urlencode 'q werty=/;'
q+werty%3D%2F%3B
Run Code Online (Sandbox Code Playgroud)

参考

  • 流媒体:`cat your_lovely_file.csv| python -c "import sys, urllib as ul; [sys.stdout.write(ul.quote_plus(l)) for l in sys.stdin]"` (20认同)

ken*_*orb 80

sed

尝试以下命令行:

$ sed 's@+@ @g;s@%@\\x@g' file | xargs -0 printf "%b"
Run Code Online (Sandbox Code Playgroud)

或使用以下替代方法echo -e

$ sed -e's/%\([0-9A-F][0-9A-F]\)/\\\\\x\1/g' file | xargs echo -e
Run Code Online (Sandbox Code Playgroud)

注意:上面的语法可能不会转换+为空格,并且可以吃掉所有的换行符。


您可以将其定义为别名并将其添加到您的 shell rc文件中:

$ alias urldecode='sed "s@+@ @g;s@%@\\\\x@g" | xargs -0 printf "%b"'
Run Code Online (Sandbox Code Playgroud)

然后每次需要时,只需使用:

$ echo "http%3A%2F%2Fwww" | urldecode
http://www
Run Code Online (Sandbox Code Playgroud)

重击

编写脚本时,您可以使用以下语法:

input="http%3A%2F%2Fwww"
decoded=$(printf '%b' "${input//%/\\x}")
Run Code Online (Sandbox Code Playgroud)

但是,上述语法无法+正确处理加号 ( ),因此您必须通过sed或按照@isaac 的建议将它们替换为空格,请使用以下语法:

decoded=$(input=${input//+/ }; printf "${input//%/\\x}")
Run Code Online (Sandbox Code Playgroud)

您还可以使用以下urlencode()urldecode()功能:

urlencode() {
    # urlencode <string>
    local length="${#1}"
    for (( i = 0; i < length; i++ )); do
        local c="${1:i:1}"
        case $c in
            [a-zA-Z0-9.~_-]) printf "$c" ;;
            *) printf '%%%02X' "'$c" ;;
        esac
    done
}

urldecode() {
    # urldecode <string>

    local url_encoded="${1//+/ }"
    printf '%b' "${url_encoded//%/\\x}"
}
Run Code Online (Sandbox Code Playgroud)

请注意,以上urldecode()假设数据不包含反斜杠。

这是在以下位置找到的类似 Joel 的版本:https : //github.com/sixarm/urldecode.sh


bash + xxd

xxd工具的Bash 功能:

urlencode() {
  local length="${#1}"
  for (( i = 0; i < length; i++ )); do
    local c="${1:i:1}"
    case $c in
      [a-zA-Z0-9.~_-]) printf "$c" ;;
    *) printf "$c" | xxd -p -c1 | while read x;do printf "%%%s" "$x";done
  esac
done
}
Run Code Online (Sandbox Code Playgroud)

cdown 的 gist 文件中找到,也在stackoverflow 中找到


PHP

使用 PHP,您可以尝试以下命令:

$ echo oil+and+gas | php -r 'echo urldecode(fgets(STDIN));' // Or: php://stdin
oil and gas
Run Code Online (Sandbox Code Playgroud)

要不就:

php -r 'echo urldecode("oil+and+gas");'
Run Code Online (Sandbox Code Playgroud)

使用-R多线路输入。


珀尔

在 Perl 中,您可以使用URI::Escape.

decoded_url=$(perl -MURI::Escape -e 'print uri_unescape($ARGV[0])' "$encoded_url")
Run Code Online (Sandbox Code Playgroud)

或处理文件:

perl -i -MURI::Escape -e 'print uri_unescape($ARGV[0])' file
Run Code Online (Sandbox Code Playgroud)

awk

尝试匿名解决方案:

awk -niord '{printf RT?$0chr("0x"substr(RT,2)):$0}' RS=%..
Run Code Online (Sandbox Code Playgroud)

注意:参数-n特定于 GNU awk

请参阅:使用 awk printf 对文本进行 urldecode

解码文件名

如果您需要从文件名中删除 url 编码,请使用deurlname工具 from renameutils(eg deurlname *.*)。

也可以看看:


有关的:

  • 您涉及 `printf` 的解决方案没有考虑到 url 可能包含像 `%25` 这样的转义百分号。您将这些传递给 printf 而不使用另一个百分比符号(如“%%”)将它们转义给 printf。 (3认同)

Gil*_*il' 18

Python 标准库中有一个内置函数。在 Python 2 中,它是urllib.unquote.

decoded_url=$(python2 -c 'import sys, urllib; print urllib.unquote(sys.argv[1])' "$encoded_url")
Run Code Online (Sandbox Code Playgroud)

或处理文件:

python2 -c 'import sys, urllib; print urllib.unquote(sys.stdin.read())' <file >file.new &&
mv -f file.new file
Run Code Online (Sandbox Code Playgroud)

在 Python 3 中,它是urllib.parse.unquote.

decoded_url=$(python3 -c 'import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))' "$encoded_url")
Run Code Online (Sandbox Code Playgroud)

或处理文件:

python3 -c 'import sys, urllib; print(urllib.parse.unquote(sys.stdin.read()))' <file >file.new &&
mv -f file.new file
Run Code Online (Sandbox Code Playgroud)

在 Perl 中,您可以使用URI::Escape.

decoded_url=$(perl -MURI::Escape -e 'print uri_unescape($ARGV[0])' "$encoded_url")
Run Code Online (Sandbox Code Playgroud)

或处理文件:

perl -i -MURI::Escape -e 'print uri_unescape($ARGV[0])' file
Run Code Online (Sandbox Code Playgroud)

如果你想坚持使用 POSIX 便携工具,那就尴尬了,因为唯一认真的候选者是 awk,它不解析十六进制数字。有关常见 awk 实现(包括 BusyBox)的示例,请参阅使用 awk printf 对文本进行urldecode


Adr*_*onk 16

Perl 一个班轮:

$ perl -pe 's/\%(\w\w)/chr hex $1/ge'
Run Code Online (Sandbox Code Playgroud)

例子:

$ echo '%21%22' |  perl -pe 's/\%(\w\w)/chr hex $1/ge'
!"
Run Code Online (Sandbox Code Playgroud)

或者,如果您想忽略非十六进制序列%zz(如上面所说的)

$ perl -pe 's/\%([[:xdigit:]]{2})/chr hex $1/ge'
Run Code Online (Sandbox Code Playgroud)

  • 只有一种在 MacOS 上对我来说很优雅。 (3认同)
  • 当您不想处理安装 perl 模块时,这个答案很有吸引力。 (2认同)

Pan*_*dya 11

如果要使用简单的sed命令,则使用以下命令:

sed -e 's/%21/!/g' -e 's/%23/#/g' -e 's/%24/$/g' -e 's/%26/\&/g' -e "s/%27/'/g" -e 's/%28/(/g' -e 's/%29/)/g'
Run Code Online (Sandbox Code Playgroud)

但是创建一个像(比如sedscript)这样的脚本更方便:

sed -e 's/%21/!/g' -e 's/%23/#/g' -e 's/%24/$/g' -e 's/%26/\&/g' -e "s/%27/'/g" -e 's/%28/(/g' -e 's/%29/)/g'
Run Code Online (Sandbox Code Playgroud)

然后运行sed -f sedscript < old > new,它将根据您的需要输出。


为方便起见,该命令urlencode也可以直接在gridsite-clients可以安装的包中使用(sudo apt-get install gridsite-clients在 Ubuntu/Debian 系统中)。

姓名

    urlencode - 将字符串与 URL 编码形式相互转换
概要

    urlencode [-m|-d] string [string ...]

描述

    urlencode 根据 RFC 1738 对字符串进行编码。

    也就是说,字符A- Z a- z 0-9 . _-未经修改地通过,但所有其他字符都表示为 %HH,其中 HH 是它们的两位大写十六进制 ASCII 表示。例如,网址http://www.gridpp.ac.uk/变为http%3A%2F%2Fwww.gridpp.ac.uk%2F

    urlencode转换命令行上给出的所有字符串中的每个字符。如果给出多个字符串,它们在转换前用分隔空格连接。

选项
    -m
      不是完全转换,而是在 AZ az 0-9 中执行 GridSite“轻度 URL 编码”。= - _ @ 和 / 未经修改地通过。这会产生稍微更易读的字符串,但应用程序必须准备好创建或模拟任何斜线隐含的目录。
    -d
      根据 RFC 1738,进行 URL 解码而不是编码。 %HH 和 %hh 字符串被转换,其他字符未经修改地通过,但+转换为空格的例外。

解码 URL 示例:

$ urlencode -d "http%3a%2f%2funix.stackexchange.com%2f"
http://unix.stackexchange.com/

$ urlencode -d "Example: %21, %22, . . . , %29 etc"
Example: !, ", . . . , ) etc
Run Code Online (Sandbox Code Playgroud)

  • 这是一个糟糕的解决方案,因为它需要对每个字符进行硬编码。您的代码缺少经常使用的“%20”转义序列就是这个问题的例证。 (5认同)

Ste*_*nny 7

GNU awk

#!/usr/bin/awk -fn
@include "ord"
BEGIN {
   RS = "%.."
}
{
   printf "%s", $0
   if (RT != "") {
      printf "%s", chr("0x" substr(RT, 2)) 
   }
}
Run Code Online (Sandbox Code Playgroud)


DIG*_*mbl 7

我无法评论此线程中的最佳答案,所以这是我的。

就个人而言,我使用这些别名进行 URL 编码和解码:

alias urlencode='python -c "import urllib, sys; print urllib.quote(  sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1])"'

alias urldecode='python -c "import urllib, sys; print urllib.unquote(sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1])"'
Run Code Online (Sandbox Code Playgroud)

这两个命令都允许您转换数据,作为命令行参数传递或从标准输入读取它,因为两个单行程序检查是否有命令行参数(甚至是空参数)并处理它们,否则仅读取标准输入。


更新 2017-05-23(斜线编码)

回应@Bevor 的评论。

如果还需要对斜杠进行编码,只需在引用函数中添加一个空的第二个参数,那么斜杠也会被编码。

所以,最后urlencode 的别名bash的看起来像这样:

alias urlencode='python -c "import urllib, sys; print urllib.quote(sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1], \"\")"'
Run Code Online (Sandbox Code Playgroud)

例子

$ urlencode "????? ????/Pen test"
%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test

$ echo "????? ????/Pen test" | urlencode
%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test

$ urldecode %D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test
????? ????/Pen test

$ echo "%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test" | urldecode
????? ????/Pen test

$ urlencode "????? ????/Pen test" | urldecode
????? ????/Pen test

$ echo "????? ????/Pen test" | urlencode | urldecode
????? ????/Pen test
Run Code Online (Sandbox Code Playgroud)


ter*_*don 5

另一种 Perl 方法:

#!/usr/bin/env perl
use URI::Encode;
my $uri     = URI::Encode->new( { encode_reserved => 0 } );
while (<>) {

    print $uri->decode($_)
}
Run Code Online (Sandbox Code Playgroud)

您将需要安装该URI::Encode模块。在我的 Debian 上,我可以简单地运行

sudo apt-get install liburi-encode-perl
Run Code Online (Sandbox Code Playgroud)

然后,我在包含以下内容的测试文件上运行上面的脚本:

sudo apt-get install liburi-encode-perl
Run Code Online (Sandbox Code Playgroud)

结果是(我将脚本保存为foo.pl):

http://foo%21asd%23asd%24%26asd%27asd%28asd%29
Run Code Online (Sandbox Code Playgroud)


小智 5

使用 ruby​​ 的另一个解决方案(接受的 python 答案对我不起作用)

alias urldecode='ruby -e "require \"cgi\"; puts CGI.unescape(ARGV[0])"'
alias urlencode='ruby -e "require \"cgi\"; puts CGI.escape(ARGV[0])"'
Run Code Online (Sandbox Code Playgroud)

例子

$ urldecode 'q+werty%3D%2F%3B'
q werty=/;

$ urlencode 'q werty=/;'
q+werty%3D%2F%3B
Run Code Online (Sandbox Code Playgroud)