使用 awk printf 对文本进行 urldecode
Posted
技术标签:
【中文标题】使用 awk printf 对文本进行 urldecode【英文标题】:Using awk printf to urldecode text 【发布时间】:2011-04-13 06:50:58 【问题描述】:我正在使用awk
对一些文本进行urldecode。
如果我将字符串编码到printf
语句中,例如printf "%s", "\x3D"
,它会正确输出=
。如果我将整个转义字符串作为变量,则相同。
但是,如果我只有3D
,我怎么能附加\x
所以printf
将打印=
而不是\x3D
?
我正在使用busybox awk 1.4.2
和ash
shell。
【问题讨论】:
【参考方案1】:我不知道你是如何在 awk 中做到这一点的,但在 perl 中是微不足道的:
echo "http://example.com/?q=foo%3Dbar" |
perl -pe 's/\+/ /g; s/%([0-9a-f]2)/chr(hex($1))/eig'
【讨论】:
谢谢,但是 perl 不可用。 @zwol 如果您使用反斜杠转义+
,这仅适用于 Perl 5!顺便说一句,完全没有 s/\+/ /g
部分的示例 URL 对我来说很好用!单独的第二个正则表达式已经可以解决问题了。
@syntaxerror 你说的很对 +
需要转义,不知道我是怎么错过的。我认为?q=phrase+separated+by+plus+signs
符号自从我写这篇文章以来已经不那么常见了,但它仍然是spec for application/x-www-form-urlencoded 表单提交转义的一部分。
哦,你是对的,我忘记了那些表单提交。但是,由于我的主要目标是修复“乱码”下载链接,所以最重要的是首先摆脱所有这些 %20
、%3D
和 %3F
(等)的东西。【参考方案2】:
由于您使用的是 ash 而 Perl 不可用,我假设您可能没有 gawk
。
对我来说,使用 gawk
或 busybox awk,您的第二个示例与第一个示例的工作方式相同(我从两者都得到“=”),除非我使用 --posix
选项(其中如果我得到 both 的“x3D”)。
如果我将--non-decimal-data
或--traditional
与gawk
一起使用,我会得到“=”。
您使用的是什么版本的 AWK(awk
、nawk
、gawk
、busybox - 和版本号)?
编辑:
您可以通过添加零将变量的字符串值强制转换为数字:
~/busybox/awk 'BEGIN string="3D"; pre="0x"; hex=pre string; printf "%c", hex+0'
【讨论】:
你说得对,它确实有效。我问错了问题 - 我会修改它。 (我使用的是busybox awk,版本1.4.2) 我花了很长时间才意识到这个单行代码仅适用于 one 变量,没有完整的 urlencoded 字符串(例如,用%20
和 %3F
填充的网址东西)【参考方案3】:
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=%..
Decoding URL encoding (percent encoding)
【讨论】:
这是乱码,例如UTF-8 编码的非 ASCII 字符【参考方案4】:这依赖于 gnu awk 对 split 函数的扩展,但这是可行的:
gawk ' numElems = split($0, arr, /%../, seps);
outStr = ""
for (i = 1; i <= numElems - 1; i++)
outStr = outStr arr[i]
outStr = outStr sprintf("%c", strtonum("0x" substr(seps[i],2)))
outStr = outStr arr[i]
print outStr
'
【讨论】:
【参考方案5】:首先,我知道这是一个老问题,但没有一个答案对我有用(仅限于 busybox awk)
两个选项。解析标准输入:
awk 'for (y=0;y<127;y++) if (y!=37) gsub(sprintf("%%%02x|%%%02X",y,y), y==38 ? "\\&" : sprintf("%c", y));gsub(/%25/, "%");print'
获取命令行参数:
awk 'BEGIN for (y=0;y<127;y++) if (y!=37) gsub(sprintf("%%%02x|%%%02X",y,y), y==38 ? "\\&" : sprintf("%c", y), ARGV[1]);gsub(/%25/, "%", ARGV[1]);print ARGV[1]' parameter
必须最后执行 %25,否则像 %253D 这样的字符串会被双重解析,这是不应该发生的。
y==38 的内联检查是因为 gsub 将 & 视为特殊字符,除非您使用反斜杠。
【讨论】:
以上是关于使用 awk printf 对文本进行 urldecode的主要内容,如果未能解决你的问题,请参考以下文章