【问题标题】:Using awk printf to urldecode text使用 awk printf 对文本进行 urldecode
【发布时间】:2011-04-13 06:50:58
【问题描述】:

我正在使用awk 对一些文本进行urldecode。

如果我将字符串编码到printf 语句中,例如printf "%s", "\x3D",它会正确输出=。如果我将整个转义字符串作为变量,则相同。

但是,如果我只有3D,我怎么能附加\x 所以printf 将打印= 而不是\x3D

我正在使用busybox awk 1.4.2ash shell。

【问题讨论】:

    标签: awk printf urldecode busybox


    【解决方案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

    对我来说,使用 gawkbusybox awk,您的第二个示例与第一个示例的工作方式相同(我从两者都得到“=”),除非我使用 --posix 选项(其中如果我得到 both 的“x3D”)。

    如果我将--non-decimal-data--traditionalgawk 一起使用,我会得到“=”。

    您使用的是什么版本的 AWK(awknawkgawk、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 将 & 视为特殊字符,除非您使用反斜杠。

      【讨论】:

        猜你喜欢
        • 2013-03-03
        • 1970-01-01
        • 2016-01-14
        • 1970-01-01
        • 2021-07-19
        • 1970-01-01
        • 1970-01-01
        • 2018-06-21
        • 1970-01-01
        相关资源
        最近更新 更多