如何在命令行上编码和解码百分比编码的字符串?


31

如何在命令行上编码和解码百分比编码(URL编码)的字符串?

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

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

您是否也要合并不同的编码?%E6ndr%FCk在我看来不像(标准)UTF8。还是只是一个例子?
安排

@arrange感谢您抓住这一点。显然,我在在线转换器的搜索结果中选择了坏苹果
ændrük

有关文件名,请参阅:如何在文件名中删除URI编码
kenorb 2015年

Answers:


35

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

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.quoteurllib.quote_plus

我猜您将要为它们别名 ;-)


1
第一行末尾的那个æ字符是什么?编辑:对我自己回答-知道了,它只是单个字符UTF8要编码的字符串,例如,目的是:-)
TMG

1
python3怎么样?
RicardoE

@RicardoE检查此答案
Pablo A

27

贝壳

请尝试以下命令行:

$ 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

重击

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

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()假定数据不包含反斜杠。


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找到


蟒蛇

尝试定义以下别名:

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中,您可以使用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

尝试匿名解决方案:

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

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


解码文件名

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

也可以看看:


有关:


bash + xxd版本不适用于包含a的字符串%,也许您可​​以替换printf "$c"printf "%c" "$c"?另一个问题是,某些ä语言设置中未对某些非ASCII字符进行编码(例如),可能export LC_ALL=C在函数中添加了“ a ”(这不应影响函数外部的任何内容)?
12431234123412341234123

8

百分比编码的保留URI字符和非ASCII字符

jq -s -R -r @uri

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

对所有字符进行百分比编码

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

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

对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=这将在替换字符IFS%00。如果没有LC_ALL=C这将例如替换%3042在UTF-8语言环境。


5

纯bash解决方案,仅用于解码

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

4

我无法在此主题中评论最佳答案,所以这是我的。

我个人使用以下别名进行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])"'

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

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

...根据@muru评论。

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

如果还需要对斜杠进行编码,只需在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
我认为sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1]可能更合适。尤其是如果您在脚本中使用此命令,并且不小心输入了空的第一个参数。
muru

根据@muru注释,我更改了在命令行中对参数的检查。它是: len(sys.argv) < 2 and sys.stdin.read()[0:-1] or sys.argv[1] 现在: sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1] 也就是说,即使第一个参数为空,该命令也不会等待标准输入的输入,而是会处理一个空参数。
DIG mbl

2

我找到了一个包,renameutils其中包含实用程序deurlname,该实用程序能够重命名包含“百分比编码”字符的文件。

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

没有关于编码部分的信息,即使因为对哪些字符进行编码可能存在疑问。只有非ASCII吗?

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


1

Stefano ansqer相似,但在Python 3中:

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

要编码也要斜杠:

python -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1], \"\"))"

有关此处差异的更多信息。


0

这是用于编码的POSIX Awk函数:

function encodeURIComponent(str, j, q) {
  while (y++ < 125) z[sprintf("%c", y)] = y
  while (y = substr(str, ++j, 1))
    q = y ~ /[[:alnum:]_.!~*\47()-]/ ? q y : q sprintf("%%%02X", z[y])
  return q
}

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.