如何来urlencode为curl命令数据?如何来urlencode为curl命令数据?(How t

2019-05-10 11:51发布

我想写一个用于测试的bash脚本,需要一个参数,并将其发送至卷曲网站。 我需要URL编码值,以确保特殊字符正确处理。 做这个的最好方式是什么?

这是我的基本的脚本至今:

#!/bin/bash
host=${1:?'bad host'}
value=$2
shift
shift
curl -v -d "param=${value}" http://${host}/somepath $@

Answer 1:

使用curl --data-urlencode ; 从man curl

该数据发布,类似于其他--data与此进行URL编码例外选项。 为CGI-柔顺的,所述<data>部分应该用名称后跟分隔符和内容规范开始。

实例:

curl \
    --data-urlencode "paramName=value" \
    --data-urlencode "secondParam=value" \
    http://example.com

请参见手册页获得更多信息。

这需要卷曲7.18.0或更高版本(2008年1月发布) 。 使用curl -V检查您所拥有的版本。



Answer 2:

这里是纯粹的BASH答案。

rawurlencode() {
  local string="${1}"
  local strlen=${#string}
  local encoded=""
  local pos c o

  for (( pos=0 ; pos<strlen ; pos++ )); do
     c=${string:$pos:1}
     case "$c" in
        [-_.~a-zA-Z0-9] ) o="${c}" ;;
        * )               printf -v o '%%%02x' "'$c"
     esac
     encoded+="${o}"
  done
  echo "${encoded}"    # You can either set a return variable (FASTER) 
  REPLY="${encoded}"   #+or echo the result (EASIER)... or both... :p
}

您可以通过两种方式使用:

easier:  echo http://url/q?=$( rawurlencode "$args" )
faster:  rawurlencode "$args"; echo http://url/q?${REPLY}

[编辑]

这里的匹配rawurldecode()函数,它 - 与所有谦虚 - 真棒。

# Returns a string in which the sequences with percent (%) signs followed by
# two hex digits have been replaced with literal characters.
rawurldecode() {

  # This is perhaps a risky gambit, but since all escape characters must be
  # encoded, we can replace %NN with \xNN and pass the lot to printf -b, which
  # will decode hex for us

  printf -v REPLY '%b' "${1//%/\\x}" # You can either set a return variable (FASTER)

  echo "${REPLY}"  #+or echo the result (EASIER)... or both... :p
}

随着配套设置,现在我们可以进行一些简单的测试:

$ diff rawurlencode.inc.sh \
        <( rawurldecode "$( rawurlencode "$( cat rawurlencode.inc.sh )" )" ) \
        && echo Matched

Output: Matched

如果你真的觉得你需要一个外部工具(当然,它就会快很多,而且可能做的二进制文件,这样......)我发现这是我的OpenWRT路由器...

replace_value=$(echo $replace_value | sed -f /usr/lib/ddns/url_escape.sed)

凡url_escape.sed是包含这些规则的文件:

# sed url escaping
s:%:%25:g
s: :%20:g
s:<:%3C:g
s:>:%3E:g
s:#:%23:g
s:{:%7B:g
s:}:%7D:g
s:|:%7C:g
s:\\:%5C:g
s:\^:%5E:g
s:~:%7E:g
s:\[:%5B:g
s:\]:%5D:g
s:`:%60:g
s:;:%3B:g
s:/:%2F:g
s:?:%3F:g
s^:^%3A^g
s:@:%40:g
s:=:%3D:g
s:&:%26:g
s:\$:%24:g
s:\!:%21:g
s:\*:%2A:g


Answer 3:

使用Perl的URI::Escape模块和uri_escape功能在你的bash脚本的第二行:

...

value="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "$2")"
...

编辑:固定报价的问题,由克里斯·约翰森在评论建议。 谢谢!



Answer 4:

为了完整起见,采用了许多解决方案, sedawk只翻译了特殊的字符集,并因此由代码尺寸相当大,也翻译不应该被编码的其他特殊字符。

来urlencode一个安全的方式是只每一个字节编码 - 甚至那些已经被允许的。

echo -ne 'some random\nbytes' | xxd -plain | tr -d '\n' | sed 's/\(..\)/%\1/g'

XXD这里照顾了输入作为字节,而不是字符处理。

编辑:

XXD附带在Debian VIM-common软件包,我只是它没有安装在系统上,我没有想安装它。 该altornative是使用hexdump从bsdmainutils包在Debian中。 根据下面的图,bsdmainutils和VIM-共同应必须安装一个大约相等的可能性:

http://qa.debian.org/popcon-png.php?packages=vim-common%2Cbsdmainutils&show_installed=1&want_legend=1&want_ticks=1

但仍然在这里,它使用一个版本hexdump代替xxd ,并允许避免tr电话:

echo -ne 'some random\nbytes' | hexdump -v -e '/1 "%02x"' | sed 's/\(..\)/%\1/g'


Answer 5:

一个变种,可能是丑陋的,但简单的:

urlencode() {
    local data
    if [[ $# != 1 ]]; then
        echo "Usage: $0 string-to-urlencode"
        return 1
    fi
    data="$(curl -s -o /dev/null -w %{url_effective} --get --data-urlencode "$1" "")"
    if [[ $? != 3 ]]; then
        echo "Unexpected error" 1>&2
        return 2
    fi
    echo "${data##/?}"
    return 0
}

这里是单行版本例如(通过建议的布鲁诺 ):

date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3-


Answer 6:

我觉得在Python更具可读性:

encoded_value=$(python -c "import urllib; print urllib.quote('''$value''')")

三重“保证价值单引号不会受到伤害。 urllib的是在标准库。 它exampple这个疯狂的(现实世界)网址工作​​:

"http://www.rai.it/dl/audio/" "1264165523944Ho servito il re d'Inghilterra - Puntata 7


Answer 7:

我发现下面的代码片段很有用它粘成程序调用,其中URI ::逃生可能未安装的链条:

perl -p -e 's/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg'

( 源 )



Answer 8:

另一种选择是使用jq

jq -sRr @uri

-R--raw-input )把输入线作为字符串代替解析它们作为JSON和-sR--slurp --raw-input )读取输入到一个单一的字符串。 -r--raw-output )输出字符串而非JSON字符串文字的内容。

如果输入不包含换行符(或者你不想逃避他们为%0A ),您可以只使用jq -Rr @uri没有-s选项。

或者这百分号编码的所有字节:

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


Answer 9:

如果你想运行GET请求,并用纯卷曲只需添加--get到@雅各布的解决方案。

下面是一个例子:

curl -v --get --data-urlencode "access_token=$(cat .fb_access_token)" https://graph.facebook.com/me/feed


Answer 10:

直接链接到awk的版本: http://www.shelldorado.com/scripts/cmds/urlencode
我用了多年,它的工作原理就像一个魅力

:
##########################################################################
# Title      :  urlencode - encode URL data
# Author     :  Heiner Steven (heiner.steven@odn.de)
# Date       :  2000-03-15
# Requires   :  awk
# Categories :  File Conversion, WWW, CGI
# SCCS-Id.   :  @(#) urlencode  1.4 06/10/29
##########################################################################
# Description
#   Encode data according to
#       RFC 1738: "Uniform Resource Locators (URL)" and
#       RFC 1866: "Hypertext Markup Language - 2.0" (HTML)
#
#   This encoding is used i.e. for the MIME type
#   "application/x-www-form-urlencoded"
#
# Notes
#    o  The default behaviour is not to encode the line endings. This
#   may not be what was intended, because the result will be
#   multiple lines of output (which cannot be used in an URL or a
#   HTTP "POST" request). If the desired output should be one
#   line, use the "-l" option.
#
#    o  The "-l" option assumes, that the end-of-line is denoted by
#   the character LF (ASCII 10). This is not true for Windows or
#   Mac systems, where the end of a line is denoted by the two
#   characters CR LF (ASCII 13 10).
#   We use this for symmetry; data processed in the following way:
#       cat | urlencode -l | urldecode -l
#   should (and will) result in the original data
#
#    o  Large lines (or binary files) will break many AWK
#       implementations. If you get the message
#       awk: record `...' too long
#        record number xxx
#   consider using GNU AWK (gawk).
#
#    o  urlencode will always terminate it's output with an EOL
#       character
#
# Thanks to Stefan Brozinski for pointing out a bug related to non-standard
# locales.
#
# See also
#   urldecode
##########################################################################

PN=`basename "$0"`          # Program name
VER='1.4'

: ${AWK=awk}

Usage () {
    echo >&2 "$PN - encode URL data, $VER
usage: $PN [-l] [file ...]
    -l:  encode line endings (result will be one line of output)

The default is to encode each input line on its own."
    exit 1
}

Msg () {
    for MsgLine
    do echo "$PN: $MsgLine" >&2
    done
}

Fatal () { Msg "$@"; exit 1; }

set -- `getopt hl "$@" 2>/dev/null` || Usage
[ $# -lt 1 ] && Usage           # "getopt" detected an error

EncodeEOL=no
while [ $# -gt 0 ]
do
    case "$1" in
        -l) EncodeEOL=yes;;
    --) shift; break;;
    -h) Usage;;
    -*) Usage;;
    *)  break;;         # First file name
    esac
    shift
done

LANG=C  export LANG
$AWK '
    BEGIN {
    # We assume an awk implementation that is just plain dumb.
    # We will convert an character to its ASCII value with the
    # table ord[], and produce two-digit hexadecimal output
    # without the printf("%02X") feature.

    EOL = "%0A"     # "end of line" string (encoded)
    split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ")
    hextab [0] = 0
    for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0
    if ("'"$EncodeEOL"'" == "yes") EncodeEOL = 1; else EncodeEOL = 0
    }
    {
    encoded = ""
    for ( i=1; i<=length ($0); ++i ) {
        c = substr ($0, i, 1)
        if ( c ~ /[a-zA-Z0-9.-]/ ) {
        encoded = encoded c     # safe character
        } else if ( c == " " ) {
        encoded = encoded "+"   # special handling
        } else {
        # unsafe character, encode it as a two-digit hex-number
        lo = ord [c] % 16
        hi = int (ord [c] / 16);
        encoded = encoded "%" hextab [hi] hextab [lo]
        }
    }
    if ( EncodeEOL ) {
        printf ("%s", encoded EOL)
    } else {
        print encoded
    }
    }
    END {
        #if ( EncodeEOL ) print ""
    }
' "$@"


Answer 11:

这可能是最好的一个:

after=$(echo -e "$before" | od -An -tx1 | tr ' ' % | xargs printf "%s")


Answer 12:

url=$(echo "$1" | sed -e 's/%/%25/g' -e 's/ /%20/g' -e 's/!/%21/g' -e 's/"/%22/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' -e 's/\*/%2a/g' -e 's/+/%2b/g' -e 's/,/%2c/g' -e 's/-/%2d/g' -e 's/\./%2e/g' -e 's/\//%2f/g' -e 's/:/%3a/g' -e 's/;/%3b/g' -e 's//%3e/g' -e 's/?/%3f/g' -e 's/@/%40/g' -e 's/\[/%5b/g' -e 's/\\/%5c/g' -e 's/\]/%5d/g' -e 's/\^/%5e/g' -e 's/_/%5f/g' -e 's/`/%60/g' -e 's/{/%7b/g' -e 's/|/%7c/g' -e 's/}/%7d/g' -e 's/~/%7e/g')

这将字符串编码的$ 1和$网址输出它的内部。 虽然你不必把它放在一个变种,如果你想要的。 BTW没有包括的sed的标签想到会变成空格



Answer 13:

这里是不调用任何外部程序的解决方案猛砸:

uriencode() {
  s="${1//'%'/%25}"
  s="${s//' '/%20}"
  s="${s//'"'/%22}"
  s="${s//'#'/%23}"
  s="${s//'$'/%24}"
  s="${s//'&'/%26}"
  s="${s//'+'/%2B}"
  s="${s//','/%2C}"
  s="${s//'/'/%2F}"
  s="${s//':'/%3A}"
  s="${s//';'/%3B}"
  s="${s//'='/%3D}"
  s="${s//'?'/%3F}"
  s="${s//'@'/%40}"
  s="${s//'['/%5B}"
  s="${s//']'/%5D}"
  printf %s "$s"
}


Answer 14:

对于那些你在寻找一个不需要perl的一个解决方案,这里是一个只需要hexdump都和awk:

url_encode() {
 [ $# -lt 1 ] && { return; }

 encodedurl="$1";

 # make sure hexdump exists, if not, just give back the url
 [ ! -x "/usr/bin/hexdump" ] && { return; }

 encodedurl=`
   echo $encodedurl | hexdump -v -e '1/1 "%02x\t"' -e '1/1 "%_c\n"' |
   LANG=C awk '
     $1 == "20"                    { printf("%s",   "+"); next } # space becomes plus
     $1 ~  /0[adAD]/               {                      next } # strip newlines
     $2 ~  /^[a-zA-Z0-9.*()\/-]$/  { printf("%s",   $2);  next } # pass through what we can
                                   { printf("%%%s", $1)        } # take hex value of everything else
   '`
}

从一对夫妇的跨网和一些地方的试验和错误的地方缝合在一起。 它的伟大工程!



Answer 15:

从一个shell脚本使用PHP:

value="http://www.google.com"
encoded=$(php -r "echo rawurlencode('$value');")
# encoded = "http%3A%2F%2Fwww.google.com"
echo $(php -r "echo rawurldecode('$encoded');")
# returns: "http://www.google.com"
  1. http://www.php.net/manual/en/function.rawurlencode.php
  2. http://www.php.net/manual/en/function.rawurldecode.php


Answer 16:

uni2ascii是非常方便的:

$ echo -ne '你好世界' | uni2ascii -aJ
%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C


Answer 17:

如果你不希望依赖于Perl的,你也可以使用SED。 这是一个有点乱,因为每个角色都可以独立逃脱。 使文件具有以下内容并把它urlencode.sed

s/%/%25/g
s/ /%20/g
s/ /%09/g
s/!/%21/g
s/"/%22/g
s/#/%23/g
s/\$/%24/g
s/\&/%26/g
s/'\''/%27/g
s/(/%28/g
s/)/%29/g
s/\*/%2a/g
s/+/%2b/g
s/,/%2c/g
s/-/%2d/g
s/\./%2e/g
s/\//%2f/g
s/:/%3a/g
s/;/%3b/g
s//%3e/g
s/?/%3f/g
s/@/%40/g
s/\[/%5b/g
s/\\/%5c/g
s/\]/%5d/g
s/\^/%5e/g
s/_/%5f/g
s/`/%60/g
s/{/%7b/g
s/|/%7c/g
s/}/%7d/g
s/~/%7e/g
s/      /%09/g

要使用它做到以下几点。

STR1=$(echo "https://www.example.com/change&$ ^this to?%checkthe@-functionality" | cut -d\? -f1)
STR2=$(echo "https://www.example.com/change&$ ^this to?%checkthe@-functionality" | cut -d\? -f2)
OUT2=$(echo "$STR2" | sed -f urlencode.sed)
echo "$STR1?$OUT2"

这将字符串分割成需要编码的一部分,这是没有问题的一部分,编码需要它的一部分,然后缝合到一起。

你可以将它放入了方便sh脚本,也许有它需要的参数进行编码,把它放在你的路径,然后你可以拨打:

urlencode https://www.exxample.com?isThisFun=HellNo

资源



Answer 18:

这里的节点版本:

uriencode() {
  node -p "encodeURIComponent('${1//\'/\\\'}')"
}


Answer 19:

现在的问题是关于在bash这样做的,没有必要对Python或Perl作为其实也有一个命令,你想要做什么 - “进行urlencode”。

value=$(urlencode "${2}")

这也是好多了,因为上面的perl的答案,例如,不正确编码的所有字符。 与长划线从Word获得试试吧,你会得到错误的编码。

注意,你需要“gridsite的客户端”安装到提供此命令。



Answer 20:

你可以效仿JavaScript的encodeURIComponent在Perl。 这里的命令:

perl -pe 's/([^a-zA-Z0-9_.!~*()'\''-])/sprintf("%%%02X", ord($1))/ge'

您可以设置这是在bash别名.bash_profile

alias encodeURIComponent='perl -pe '\''s/([^a-zA-Z0-9_.!~*()'\''\'\'''\''-])/sprintf("%%%02X",ord($1))/ge'\'

现在,你可以管到encodeURIComponent

$ echo -n 'hèllo wôrld!' | encodeURIComponent
h%C3%A8llo%20w%C3%B4rld!


Answer 21:

简单的PHP选项:

echo 'part-that-needs-encoding' | php -R 'echo urlencode($argn);'


Answer 22:

另一个PHP的方法:

echo "encode me" | php -r "echo urlencode(file_get_contents('php://stdin'));"


Answer 23:

红宝石,为了完整

value="$(ruby -r cgi -e 'puts CGI.escape(ARGV[0])' "$2")"


Answer 24:

这里是我的版本的busybox的灰壳用于嵌入式系统,我原采用Orwellophile的变种:

urlencode()
{
    local S="${1}"
    local encoded=""
    local ch
    local o
    for i in $(seq 0 $((${#S} - 1)) )
    do
        ch=${S:$i:1}
        case "${ch}" in
            [-_.~a-zA-Z0-9]) 
                o="${ch}"
                ;;
            *) 
                o=$(printf '%%%02x' "'$ch")                
                ;;
        esac
        encoded="${encoded}${o}"
    done
    echo ${encoded}
}

urldecode() 
{
    # urldecode <string>
    local url_encoded="${1//+/ }"
    printf '%b' "${url_encoded//%/\\x}"
}


Answer 25:

下面是一个POSIX功能做到这一点:

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

例:

value=$(encodeURIComponent "$2")

资源



Answer 26:

这里有一个在线变换使用Lua,类似于blueyed的答案 ,除了与所有的RFC 3986个保留字元留下未编码(像这个答案 ):

url=$(echo 'print((arg[1]:gsub("([^%w%-%.%_%~])",function(c)return("%%%02X"):format(c:byte())end)))' | lua - "$1")

此外,您可能需要确保在字符串中的换行符从LF转换成CRLF,在这种情况下,你可以插入一个gsub("\r?\n", "\r\n")的percent-前链编码。

这里的一个变型中,在应用程序的非标准风格/ X WWW的窗体-urlencoded ,是否换行符正常化,以及对编码空格作为“+”,而不是“%20”(其很可能被添加到Perl中使用类似的技术)片段。

url=$(echo 'print((arg[1]:gsub("\r?\n", "\r\n"):gsub("([^%w%-%.%_%~ ]))",function(c)return("%%%02X"):format(c:byte())end):gsub(" ","+"))' | lua - "$1")


Answer 27:

有PHP的安装我用这样的方式:

URL_ENCODED_DATA=`php -r "echo urlencode('$DATA');"`


Answer 28:

这是包含rawurlencode和rawurldecode功能orwellophile的答案的KSH版本(链接: ?如何来urlencode为curl命令数据 )。 我没有足够的代表处发表评论,因此,新的职位..

#!/bin/ksh93

function rawurlencode
{
    typeset string="${1}"
    typeset strlen=${#string}
    typeset encoded=""

    for (( pos=0 ; pos<strlen ; pos++ )); do
        c=${string:$pos:1}
        case "$c" in
            [-_.~a-zA-Z0-9] ) o="${c}" ;;
            * )               o=$(printf '%%%02x' "'$c")
        esac
        encoded+="${o}"
    done
    print "${encoded}"
}

function rawurldecode
{
    printf $(printf '%b' "${1//%/\\x}")
}

print $(rawurlencode "C++")     # --> C%2b%2b
print $(rawurldecode "C%2b%2b") # --> C++


Answer 29:

什么会解析的网址不是JavaScript更好?

node -p "encodeURIComponent('$url')"


Answer 30:

以下是根据Orwellophile的回答,但解决了通过设置LC_ALL = C(从vte.sh一招)在评论中提到的多字节错误。 我写它的功能适合PROMPT_COMMAND形式,因为这是我如何使用它。

print_path_url() {
  local LC_ALL=C
  local string="$PWD"
  local strlen=${#string}
  local encoded=""
  local pos c o

  for (( pos=0 ; pos<strlen ; pos++ )); do
     c=${string:$pos:1}
     case "$c" in
        [-_.~a-zA-Z0-9/] ) o="${c}" ;;
        * )               printf -v o '%%%02x' "'$c"
     esac
     encoded+="${o}"
  done
  printf "\033]7;file://%s%s\007" "${HOSTNAME:-}" "${encoded}"
}


文章来源: How to urlencode data for curl command?