当前位置: 首页>>技术问答>>正文


如何在命令行上编码和解码percent-encoded字符串?

, , , , ,

问题描述

如何在命令行上编码和解码percent-encoded(URL编码)字符串?

我正在寻找可以做到这一点的解决方案:

$ percent-encode "ændrük"
%C3%A6ndr%C3%BCk
$ percent-decode "%C3%A6ndr%C3%BCk"
ændrük

最佳解决思路

这些命令可以满足您的需求:

python -c "import urllib, sys; print urllib.quote(sys.argv[1])" æ
python -c "import urllib, sys; print urllib.unquote(sys.argv[1])" %C3%A6

如果要将空格编码为+,请将urllib.quote替换为urllib.quote_plus

我猜你会想要如何创建一个永久“alias”? 😉

次佳解决思路

shell

请尝试以下命令行:

$ echo "%C3%A6ndr%C3%BCk" | sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
ændrük

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

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

然后,每当您需要它时,只需使用:

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

bash

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

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

但是上面的语法不能正确处理加号(+),因此您需要通过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}"
}

Note that your urldecode() assumes the data contains no backslash.


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
}

发现于cdown’s gist file,也位于stackoverflow


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

用法:

$ urlencode "ændrük"
C%26ndrC%3Ck
$ urldecode "%C3%A6ndr%C3%BCk"
ændrük

资料来源:ruslanspivak


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

在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

sed

使用sed可以通过以下方式实现:

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

awk

试试anon解决方案:

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

请参阅:Using awk printf to urldecode text


解码文件名

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

也可以看看:


有关:

第三种解决思路

Percent-encode保留URI字符和non-ASCII字符

jq -s -R -r @uri

-s(--slurp)将输入行读入数组,-s -R(--slurp --raw-input)将输入读入单个字符串。 -r(--raw-output)输出字符串的内容而不是JSON字符串文字。

Percent-encode所有人物

xxd -p|tr -d \\n|sed 's/../%&/g'

tr -d \\n删除每60个字符后由xxd -p添加的换行符。

Percent-encode除Bash中的ASCII字母数字字符外的所有字符

eu () {
    local LC_ALL=C c
    while IFS= read -r -n1 -d '' c
    do 
        if [[ $c = [[:alnum:]] ]]
        then 
            printf %s "$c"
        else
            printf %%%02x "'$c"
        fi
    done
}

如果没有-d '',这将跳过换行符和空字节。如果没有IFS=,这将用%00替换IFS中的字符。没有LC_ALL=C,这将例如用UTF-8场所中的%3042替换

第四种思路

仅用于解码的纯bash解决方案:

$ a='%C3%A6ndr%C3%BCk'
$ echo -e "${a//%/\\x}"
ændrük

第五种思路

我无法评论best answer in this thread,所以这是我的。

就个人而言,我使用这些别名进行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])"'

这两个命令都允许您转换数据,作为命令行参数传递或从标准输入读取,因为one-liners检查是否存在命令行参数(甚至是空参数)并处理它们或者只读取标准输入。

更新2015-07-16(空第1个arg)

……根据@muru评论。

更新2017-05-28(斜杠编码)

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

所以,最后Bash中的urlencode别名如下所示:

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

第六种思路

我找到了一个包renameutils,它包含实用程序deurlname,它能够重命名包含”percent-encoded”字符的文件。

不幸的是,它不解码stdin或命令行选项,而只重命名文件,因此你必须创建一个虚拟文件来获取解码(重命名文件的名称),但是使用一些bash脚本可以自动化该过程。

没有关于编码部分的信息,即使因为编码哪些字符可能有问题。只有non-ASCII?

我认为应该有一些更好的工具/方法。

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/6461.html,未经允许,请勿转载。