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


100

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

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

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

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

等等。


Answers:


107

找到了这些可以满足您需求的Python一类衬板:

$ 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])"'

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

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

参考文献


我很晚才知道,但是有什么办法可以通过原位编辑来做到这一点?
DisplayName 2014年

@DisplayName-听起来像是我的新Q。我会问一下,并参考一下。
slm

15
流媒体:cat your_lovely_file.csv| python -c "import sys, urllib as ul; [sys.stdout.write(ul.quote_plus(l)) for l in sys.stdin]"
kirill_igum 2015年

5
注意,这是Python 2;在python默认情况下为3 的系统上,这将导致错误。改变pythonpython2您有帮助。
伊万·科尔米切克

4
因为python3您可以使用import urllib.parse as ul代替import urllib as ul
ibotty

61

sed

请尝试以下命令行:

$ sed 's@+@ @g;s@%@\\x@g' file | xargs -0 printf "%b"

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

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

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


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

$ alias urldecode='sed "s@+@ @g;s@%@\\\\x@g" | xargs -0 printf "%b"'

然后,每当您需要时,只需进行以下操作:

$ echo "http%3A%2F%2Fwww" | urldecode
http://www

重击

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

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

但是上述语法无法+正确处理pluses(),因此您必须通过来将其替换为空格sed

您还可以使用以下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}"
}

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

这是类似Joel的版本,位于:https : //github.com/sixarm/urldecode.sh


bash + xxd

Bash功能与xxd工具:

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
}

cdown的gist文件中也可以在stackoverflow找到


的PHP

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

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

要不就:

php -r 'echo urldecode("oil+and+gas");'

使用-R多线路输入。


佩尔

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

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

或处理文件:

perl -i -MURI::Escape -e 'print uri_unescape($ARGV[0])' file

awk

尝试匿名解决方案:

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

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

请参阅:使用awk printf对文本进行url解码

解码文件名

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

也可以看看:


有关:


1
awk:由于这利用了库函数,chr()因此很有可能仅在GNU awk(gawk)上运行。但是,在这种情况下,几乎没有POSIX的等效项awk,因为该-n选项(允许非十进制参数) GNU awk专业。
语法错误

您的第一个sed代码为我xargs: argument line too long提供了一个≥2164行的文件。
Sparhawk

2
您所涉及的解决方案printf未考虑到url可能包含转义的百分比符号,例如%25。您可以将它们传递给printf,而不必使用另一个百分号将它们转义为printf %%
josch 2016年

1
bash版本要求local LC_ALL=C在顶部,否则所有宽字符(即日语,中文等)都不能正确分成字节。
Phernost


18

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

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

或处理文件:

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

在Python 3中为urllib.parse.unquote

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

或处理文件:

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

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

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

或处理文件:

perl -i -MURI::Escape -e 'print uri_unescape($ARGV[0])' file

如果要坚持使用POSIX便携式工具,那会很尴尬,因为唯一的候选对象是awk,它不能解析十六进制数。有关常见awk实现(包括BusyBox)的示例,请参见使用awk printf对文本进行url解码。


10

如果要使用简单的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'

但是,创建一个类似(例如sedscript)的脚本更为方便:

s/%21/!/g
s/%23/#/g
s/%24/$/g
s/%26/\&/g
s/%27/'/g
s/%28/(/g
s/%29/)/g

然后运行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表示。例如,URL 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

有关sed 访问的
Pandya 2014年

4
这是一个不好的解决方案,因为它需要对每个字符进行硬编码。您的代码缺少经常使用的%20转义序列可以说明此问题。
2014年

@Overv我刚刚修改过
Pandya

另外,您可能需要仔细检查是什么s/%26/&/g。(我将其修复。)
G-Man



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])"'

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


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

回应@Bevor的评论。

如果还需要对斜杠进行编码,只需在quote函数中添加一个空的第二个参数,则斜杠也将被编码。

所以,最后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], \"\")"'

$ 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

1
不编码斜线。
Bevor

@Bevor:例子?
DIG mbl

在urlencode“Пробапера”中添加斜杠->结果:不对斜杠进行编码。
Bevor

1
@Bevor:你是对的。感谢您的评论。我还将更改答案以反映您的评论。
DIG mbl

4

另一种Perl方法:

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

    print $uri->decode($_)
}

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

sudo apt-get install liburi-encode-perl

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

http://foo%21asd%23asd%24%26asd%27asd%28asd%29

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

$ ./foo.pl
http://foo!asd#asd$&asd'asd(asd)

3

(主要是Posix)shell中的答案:

$ input='%21%22'
$ printf "`printf "%s\n" "$input" | sed -e 's/+/ /g' -e 's/%\(..\)/\\\\x\1/g'`"
!"

说明:

  • -e 's/+/ /g转换每个+空间(如url-encode规范中所述)
  • -e 's/%\(..\)/\\\\x\1/g'变换每个%XX\\xXX。请注意,其中一项\将通过引用规则删除。
  • 内部printf就在那里将输入传递给sed。我们可以用任何其他机制代替它
  • 外部printf解释\\xXX序列并显示结果。

编辑:

由于%应始终在URL中进行解释,因此可以简化此答案。另外,我认为使用xargs而不是反引号会更干净(由于@josch)。

$ input='%21%22+%25'
$ printf "%s\n" "$input" | sed -e 's/+/ /g; s/%/\\x/g' | xargs -0 printf
!" %

不幸的是,(如@josch所指出的)这些解决方案都不符合Posix,因为Posix \x中没有定义转义序列。


欢迎来到U&L。也许您可以解释这个答案及其作用方式。通常,我们希望答案是带有详细信息的长格式,而不仅仅是代码段。
slm

我真的很喜欢这个答案,因为它是全面,可移植的,并且不需要额外的较重的外部程序(如perl或python)。对我来说效果很好。
史蒂夫·威尔斯

1
很好的解决方案。甚至更短,更聪明:... | sed 's/+/ /g;s/%\(..\)/\\\\x\1/g'-e实际上,这里可以省略该选项...
语法错误

1
@josch是的,printf是内置的dash,它无法识别\x转义。您可以使用/usr/bin/printf代替printf以便使其工作。通常,您应该可以使用command printf,但似乎无法正常工作。它继续使用内置的。
杰罗姆Pouiller

1
@Jezz的\x转义支持确实不是POSIX的一部分:pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html 在测试期间,我看到了另一个问题。您可能希望用来替换..正则表达式,[a-zA-Z0-9][a-zA-Z0-9]因为否则“ %%%”之类的输入将失败。我还在s/%/%%/g末尾添加了以确保转义printf的百分比。
josch

1

仅外壳程序:

$ x='a%20%25%e3%81%82';printf "${x//\%/\\x}"
a %あ

添加--%b防止以破折号开头的参数被视为选项。

在zsh中${x//%/a}添加a到末尾,但${x//\%/a}替换%a


1

这是我之前写过的另一个脚本的相关内容(我只是从另一个答案中无耻地从youtube.com下载脚本中偷走了)。它使用sed和shell构建有效的urldecode。

set \! \" \# \$ \% \& \' \( \) \* \ \+ \, \/ \: \; \= \? \@ \[ \]
for c do set "$@" "'$c" "$c"; shift; done
curl -s "$url" | sed 's/\\u0026/\&/g;'"$(
    printf 's/%%%X/\\%s/g;' "$@"
)"

我不会发誓它是全面的-实际上我对此表示怀疑-但它确实可以处理youtube。


1

这是一个BASH函数,可以做到这一点:

function urldecode() {
        echo -ne $(echo -n "$1" | sed -E "s/%/\\\\x/g")
}

作品如魅力
AbdElraouf Sabri

0

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

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

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

$ urlencode 'q werty=/;'
q+werty%3D%2F%3B
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.