我想解码URL编码,是否有任何内置工具可以执行此操作,或者有人可以为我提供sed
执行此操作的代码吗?
我确实在unix.stackexchange.com和互联网上进行了一些搜索,但是找不到用于解码url编码的任何命令行工具。
我想做的就是简单地就地编辑txt
文件,以便:
%21
变成!
%23
变成#
%24
变成$
%26
变成&
%27
变成'
%28
变成(
%29
变成)
等等。
我想解码URL编码,是否有任何内置工具可以执行此操作,或者有人可以为我提供sed
执行此操作的代码吗?
我确实在unix.stackexchange.com和互联网上进行了一些搜索,但是找不到用于解码url编码的任何命令行工具。
我想做的就是简单地就地编辑txt
文件,以便:
%21
变成 !
%23
变成 #
%24
变成 $
%26
变成 &
%27
变成 '
%28
变成 (
%29
变成 )
等等。
Answers:
找到了这些可以满足您需求的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
cat your_lovely_file.csv| python -c "import sys, urllib as ul; [sys.stdout.write(ul.quote_plus(l)) for l in sys.stdin]"
python
默认情况下为3 的系统上,这将导致错误。改变python
对python2
您有帮助。
python3
您可以使用import urllib.parse as ul
代替import urllib as ul
。
请尝试以下命令行:
$ 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
工具:
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,您可以尝试以下命令:
$ 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 -niord '{printf RT?$0chr("0x"substr(RT,2)):$0}' RS=%..
注意:参数-n
特定于GNU awk
。
如果您需要从文件名中删除url编码,请使用deurlname
from工具renameutils
(例如deurlname *.*
)。
也可以看看:
有关:
awk
:由于这利用了库函数,chr()
因此很有可能仅在GNU awk(gawk
)上运行。但是,在这种情况下,几乎没有POSIX的等效项awk
,因为该-n
选项(允许非十进制参数)是 GNU awk
专业。
sed
代码为我xargs: argument line too long
提供了一个≥2164行的文件。
printf
未考虑到url可能包含转义的百分比符号,例如%25
。您可以将它们传递给printf,而不必使用另一个百分号将它们转义为printf %%
。
local LC_ALL=C
在顶部,否则所有宽字符(即日语,中文等)都不能正确分成字节。
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解码。
如果要使用简单的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表示。例如,URLhttp://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
访问的
%20
转义序列可以说明此问题。
s/%26/&/g
。(我将其修复。)
Perl一线:
$ perl -pe 's/\%(\w\w)/chr hex $1/ge'
例:
$ echo '%21%22' | perl -pe 's/\%(\w\w)/chr hex $1/ge'
!"
GNU AWK
#!/usr/bin/awk -fn
@include "ord"
BEGIN {
RS = "%.."
}
{
printf RT ? $0 chr("0x" substr(RT, 2)) : $0
}
要么
#!/bin/sh
awk -niord '{printf RT?$0chr("0x"substr(RT,2)):$0}' RS=%..
我个人使用以下别名进行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])"'
这两个命令都允许您转换作为命令行参数传递的数据或从标准输入中读取数据,因为这两个直线都检查是否有命令行参数(甚至是空参数)并处理它们,否则仅读取标准输入。
回应@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
另一种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)
(主要是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
。请注意,其中一项\
将通过引用规则删除。\\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
中没有定义转义序列。
... | sed 's/+/ /g;s/%\(..\)/\\\\x\1/g'
。-e
实际上,这里可以省略该选项...
printf
是内置的dash
,它无法识别\x
转义。您可以使用/usr/bin/printf
代替printf
以便使其工作。通常,您应该可以使用command printf
,但似乎无法正常工作。它继续使用内置的。
\x
转义支持确实不是POSIX的一部分:pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html 在测试期间,我看到了另一个问题。您可能希望用来替换..
正则表达式,[a-zA-Z0-9][a-zA-Z0-9]
因为否则“ %%%”之类的输入将失败。我还在s/%/%%/g
末尾添加了以确保转义printf的百分比。
这是我之前写过的另一个脚本的相关内容(我只是从另一个答案中无耻地从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。
这是一个BASH函数,可以做到这一点:
function urldecode() {
echo -ne $(echo -n "$1" | sed -E "s/%/\\\\x/g")
}