如何为curl命令urlencode数据?

Aar*_*ron 300 bash shell scripting curl urlencode

我正在尝试编写一个用于测试的bash脚本,它接受一个参数并通过curl将其发送到网站.我需要对值进行url编码,以确保正确处理特殊字符.做这个的最好方式是什么?

这是我到目前为止的基本脚本:

#!/bin/bash
host=${1:?'bad host'}
value=$2
shift
shift
curl -v -d "param=${value}" http://${host}/somepath $@
Run Code Online (Sandbox Code Playgroud)

Jac*_*ask 359

使用curl --data-urlencode; 来自man curl:

这会发布数据,类似于其他--data选项,但执行URL编码除外.要符合CGI,该<data>部件应以名称开头,后跟分隔符和内容规范.

用法示例:

curl \
    --data-urlencode "paramName=value" \
    --data-urlencode "secondParam=value" \
    http://example.com
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参见手册页.

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

  • @StanJames如果您使用它,那么curl也可以对GET请求进行编码.`curl -G --data-urlencode"blah = df ssdf sdf"--data-urlencode"blah2 = dfsdf sdfsd"http:// whatever.com/whatever` (76认同)
  • @kberg实际上,这只适用于查询数据.curl会附加'?' 其次是urlencoded params.如果你想urlencode一些url postfix(例如某些文档id的CouchDB GET),那么'--data-urlencode'将无效. (12认同)
  • 似乎只适用于http POST.这里的文档:http://curl.haxx.se/docs/manpage.html#-- data-urlencode (5认同)
  • 我想对 URL 路径(用作 REST API 端点中的参数)进行 URL 编码。不涉及查询字符串参数。如何针对 GET 请求执行此操作? (2认同)
  • @NadavB 逃离`"`‽ (2认同)
  • `-G, --get : 将发布数据放入 URL 并使用 GET` 来自 @kberg 的注释效果很好 (2认同)

Orw*_*ile 169

这是纯粹的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
}
Run Code Online (Sandbox Code Playgroud)

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

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

[编辑]

这是匹配的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
}
Run Code Online (Sandbox Code Playgroud)

通过匹配集,我们现在可以执行一些简单的测试:

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

Output: Matched
Run Code Online (Sandbox Code Playgroud)

如果你真的觉得你需要一个外部工具(好吧,它会更快,并且可能会做二进制文件等......)我在OpenWRT路由器上发现了这个......

replace_value=$(echo $replace_value | sed -f /usr/lib/ddns/url_escape.sed)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,这个脚本在某些字符上失败,例如'é'和'½',分别输出'e%FFFFFFFFFFFFFFCC'和'%FFFFFFFFFFFFFFC2'(我相信每个字符循环的b/c). (4认同)
  • 具有适当的 UTF-8 编码支持: `rawurlencode() { local LANG=C ; 本地 IFS= ; while read -n1 -r -d "$(echo -n "\000")" c ; 在 [-_.~a-zA-Z0-9] 中执行 case "$c") echo -n "$c" ;; *) printf '%%%02x' "'$c" ;; 经济和社会委员会;完成}`。然后:`echo -n“慢跑«à l'Hèze»。” | rawurlencode` 按预期生成 `Jogging%20%c2%ab%c3%a0%20l%27H%c3%a8ze%c2%bb.`。 (4认同)
  • 在第一个代码块中,printf 的最后一个参数是什么意思?即为什么是双引号、单引号、美元符号、字母c、双引号?单引号可以吗? (2认同)
  • @ColinFraizer 单引号用于将以下字符转换为其数值。参考 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html#tag_20_94_13 (2认同)
  • @Matthematics、@dmcontador、@Orwellophile:我的[之前的评论]是错误的(/sf/ask/20757551/#comment103082857_10660730)。[解决方案](/sf/answers/525468681/) 使用 `xxd` 更好,并且在任何情况下都有效(对于任何角色)。我已经更新了[我的脚本](https://gitlab.com/tukusejssirs/lnx_scripts/blob/master/bash_functions/rawurlencode.sh)。不管怎样,看起来“rawurldecode()”函数运行得非常好。:) (2认同)

dub*_*bek 93

在bash脚本的第二行使用Perl的URI::Escape模块和uri_escape函数:

...

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

编辑:修复引用问题,如Chris Johnsen在评论中所建议的那样.谢谢!

  • 你也不用`echo`:`value ="$(perl -MURI :: Escape -e'print uri_escape($ ARGV [0]);'"$ 2")"` (9认同)
  • 如果$ 2包含撇号,则无效. (3认同)
  • 可能没有安装URI :: Escape,在这种情况下请检查我的答案. (2认同)
  • @jrw32982 是的,回顾一下,使用另一种语言来完成这项任务是很好的。如果可以的话,我会收回我的反对票,但可惜它目前已被锁定。 (2认同)

jos*_*sch 63

为了完整起见,许多解决方案使用sedawk仅翻译一组特殊字符,因此代码大小非常大,也不会翻译应编码的其他特殊字符.

urlencode的一种安全方法是对每个字节进行编码 - 即使是那些已被允许的字节.

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

xxd在这里注意输入是作为字节而不是字符处理的.

编辑:

xxd附带了Debian中的vim-common软件包,我只是在没有安装它的系统上,我不想安装它.altornative是使用hexdumpDebian中的bsdmainutils 包.根据下图,bsdmainutils和vim-common应该具有大致相同的安装可能性:

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'
Run Code Online (Sandbox Code Playgroud)

  • 做得很好 - 很高兴看到只使用shell的单线程. (9认同)
  • @qdii确实-n缺少echo,但`xxd`调用属于`tr -d`调用.它属于那里,所以`foobar`中的任何换行都由`xxd`翻译.`xxd`调用后的`tr -d`是删除xxd产生的换行符.似乎你从来没有足够长的foobar,所以`xxd`产生换行,但是对于长输入它会.所以`tr -d`是必要的.与你的假设相反,`tr -d`不是要从输入中删除换行符,而是从`xxd`输出中删除换行符.我想在输入中保留换行符.唯一有效的一点是,echo添加了一个不必要的换行符. (4认同)
  • 如果我听起来像这样,我不是故意粗鲁.这是一个非常好的脚本,我实际上使用它:) (3认同)
  • @qdii为什么?这不仅会使urlencode新行不可能,而且还会错误地将xxd创建的换行符插入到输出中. (2认同)
  • @约施。这完全是错误的。首先,任何“\n”字符都会被“xxd -plain”翻译成“0a”。不要相信我的话,自己尝试一下:`echo -n -e '\n' | xxd -plain` 这证明你的 `tr -d '\n'` 在这里是无用的,因为在 `xxd -plain` 之后不能有任何 `\n` 其次, `echo foobar` 在中添加了自己的 `\n` 字符字符串的末尾,因此 `xxd -plain` 不会像预期那样使用 `foobar` 而是使用 `foobar\n`。然后“xxd -plain”将其转换为一些以“0a”结尾的字符串,使其不适合用户。您可以在“echo”中添加“-n”来解决它。 (2认同)
  • @josch我不知道xxd那样做了,谢谢告诉我并修复小bug :) (2认同)

小智 55

其中一个变种,可能很难看,但很简单:

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
}
Run Code Online (Sandbox Code Playgroud)

这是单行版本(例如Bruno建议):

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

# If you experience the trailing %0A, use
date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | sed -E 's/..(.*).../\1/'
Run Code Online (Sandbox Code Playgroud)

  • 这绝对是辉煌的!我真的希望你把它留下一行,以便人们可以看到它真的很简单.要对`date`命令的结果进行URL编码...`date | curl -Gso/dev/null -w%{url_effective} --data-urlencode @ - ""| cut -c 3-`(你必须'剪掉'前两个字符,因为curl的输出在技术上是一个带有查询字符串的相对URL.) (13认同)
  • 要避免在结尾处使用'%0A`,请使用`printf`而不是`echo`. (6认同)
  • @BrunoBronosky您的单行变体很好,但似乎在编码结束时添加了"%0A".用户要小心.功能版本似乎没有此问题. (2认同)
  • 一个班轮很棒 (2认同)

小智 47

我发现它在python中更具可读性:

encoded_value=$(python -c "import urllib; print urllib.quote('''$value''')")
Run Code Online (Sandbox Code Playgroud)

三重'确保单值报价不会受到伤害.urllib在标准库中.它适用于这个疯狂(真实世界)网址的例子:

"http://www.rai.it/dl/audio/" "1264165523944Ho servito il re d'Inghilterra - Puntata 7
Run Code Online (Sandbox Code Playgroud)

  • 我在引用和使用三重引号的特殊字符时遇到了一些麻烦,这似乎基本上适用于所有事情:encoded_value ="$(echo -n"$ {data}"| python -c"import urllib; import sys; sys.stdout. write(urllib.quote(sys.stdin.read()))")"; (2认同)
  • Python 3 版本将是`encoded_value=$(python3 -c "import urllib.parse; print (urllib.parse.quote('''$value'''))")`。 (2认同)
  • `urllib.parse.quote` 不编码正斜杠“/”。`urlencode() { python3 -c '导入 urllib.parse; 导入系统;print(urllib.parse.quote(sys.argv[1], safe=""))' "$1" }` (2认同)
  • 引用`sys.argv`而不是将`$ value`替换为后来被解析为代码的字符串会更安全.如果`value`包含`'''+ __import __("os").system("rm -rf~")+'''` (2认同)
  • python -c“ import urllib; print urllib.quote(raw_input())” &lt;&lt;&lt;“ $ data”` (2认同)

nis*_*ama 45

另一种选择是使用jq:

jq -sRr @uri
Run Code Online (Sandbox Code Playgroud)

-R(--raw-input)将输入行视为字符串,而不是将它们解析为JSON,并且-sR(--slurp --raw-input)将输入读入单个字符串.-r(--raw-output)输出字符串的内容而不是JSON字符串文字.

如果输入不包含换行符(或者您不想将它们转义为jq),则可以不使用-n--null-input选项.

或者这个百分比编码所有字节:

jq -nr --arg v "my shell string" '$v|@uri'
Run Code Online (Sandbox Code Playgroud)

  • &lt;3 it ... 应该是顶级的并被 IMO 接受(是的,如果你可以告诉 `curl` 来编码它的工作原理,并且如果 bash 有一个可以接受的内置函数 - 但 `jq` 似乎很适合我使用此工具远未达到舒适水平) (6认同)
  • 对于任何想和我一样的人:@uri不是变量,而是用于格式化字符串和转义的文字jq过滤器;有关详细信息,请参见[jq手册](https://stedolan.github.io/jq/manual)(对不起,没有直接链接,需要在页面上搜索`@ uri`)。 (4认同)
  • jq 进行 url 编码的示例用法: `printf "http://localhost:8082/" | jq -sRr '@uri' ` (4认同)
  • 这确实挽救了这一天,谢谢。我建议使用 Bash 的 `&lt;&lt;&lt;` (这里是字符串)而不是麻烦的 `printf`。看来最后的换行符并没有打扰`jq`:`jq -rR @uri &lt;&lt;&lt;'foo bar'`→`foo%20bar` (2认同)

blu*_*yed 30

我发现以下代码片段可用于将其粘贴到程序调用链中,其中可能未安装URI :: Escape:

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

(来源)

  • 为我工作.我将它改为perl -lpe ...(字母椭圆).这删除了我的目的所需的尾随换行符. (4认同)
  • 仅供参考,要进行相反的操作,请使用 `perl -pe 's/\%(\w\w)/chr hex $1/ge'`(来源:http://unix.stackexchange.com/questions/159253/解码-url-编码-百分比-编码) (3认同)
  • 具体取决于您需要编码的字符,您可以将其简化为"perl -pe"/(\ W)/ sprintf("%%% 02X",ord($ 1))/ ge'`,它允许使用字母,数字和下划线,但编码其他一切. (2认同)
  • 谢谢楼上的回复!由于用例是用于curl:即:`:`和`/`不需要编码,所以我的bashrc/zshrc中的最终函数是:`perl -lpe's/([^A-Za-z0-9 .\/:])/sprintf("%%%02X", ord($1))/seg` (2认同)
  • @TobiasFeil 它来自标准输入。 (2认同)

Pio*_*pla 20

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

这是一个例子:

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


che*_*wei 15

这可能是最好的一个:

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

  • 尽管这可能有效,但它会转义每个字符 (2认同)

Mat*_*euP 14

直接链接到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 ""
    }
' "$@"
Run Code Online (Sandbox Code Playgroud)


man*_*nux 10

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')
Run Code Online (Sandbox Code Playgroud)

这将编码$ 1内的字符串并将其输出为$ url.虽然如果你愿意,你不必把它放在一个var中.BTW没有包括sed for tab认为它会把它变成空格

  • 我觉得这不是*推荐的方法. (5认同)
  • 这不是推荐的方法,因为黑名单是不好的做法,无论如何这是unicode不友好. (3认同)
  • 请解释一下你的感受....因为我说的是我所说的作品而且我已经在几个剧本中使用它,所以我知道它适用于我列出的所有字符.所以请解释为什么有人不会使用我的代码并使用perl,因为标题是"来自bash脚本的URLEncode"而不是perl脚本. (2认同)

dav*_*ers 8

这是一个不调用任何外部程序的Bash解决方案:

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"
}
Run Code Online (Sandbox Code Playgroud)

  • 这在bash版本之间表现不同.在RHEL 6.9上,bash是4.1.2,它包含单引号.虽然Debian 9和bash 4.4.12对单引号很好.对我来说,删除单引号使它适用于两者.S = "$ {S // ''/%2C}" (3认同)
  • 我更新了答案以反映您的发现,@muni764。 (3认同)

Lou*_*cio 7

对于那些寻找不需要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
   '`
}
Run Code Online (Sandbox Code Playgroud)

从网上的几个地方缝合在一起并进行一些本地试验和错误.它很棒!


Dar*_*ber 7

在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"
Run Code Online (Sandbox Code Playgroud)
  1. http://www.php.net/manual/en/function.rawurlencode.php
  2. http://www.php.net/manual/en/function.rawurldecode.php


Nes*_*iza 7

什么能比 JavaScript 更好地解析 URL?

node -p "encodeURIComponent('$url')"
Run Code Online (Sandbox Code Playgroud)

  • 虽然我懒得投反对票,但这个命令的问题是它需要正确转义数据才能在 JavaScript 中使用。就像尝试用单引号和一些反斜杠疯狂一样。如果你想使用节点,你最好从标准输入中读取内容,例如 `node -p 'encodeURIComponent(require("fs").readFileSync(0))'` (4认同)

Jay*_*Jay 6

如果您不想依赖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
Run Code Online (Sandbox Code Playgroud)

要使用它,请执行以下操作.

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"
Run Code Online (Sandbox Code Playgroud)

这会将字符串拆分为需要编码的部分,而精细的部分会对需要编码的部分进行编码,然后将其拼接在一起.

你可以把它放到一个sh脚本中以方便使用,也许它需要一个参数来编码,把它放在你的路径上,然后你可以调用:

urlencode https://www.exxample.com?isThisFun=HellNo
Run Code Online (Sandbox Code Playgroud)

资源


kev*_*kev 6

uni2ascii非常方便:

$ echo -ne '????' | uni2ascii -aJ
%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于ASCII范围内的字符*,需要引用,如`%`和空格(最后可以用`-s`标志来补救) (2认同)

Kla*_*aus 6

你可以encodeURIComponent在perl中模拟javascript .这是命令:

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

您可以将其设置为bash别名.bash_profile:

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

现在你可以管道encodeURIComponent:

$ echo -n 'hèllo wôrld!' | encodeURIComponent
h%C3%A8llo%20w%C3%B4rld!
Run Code Online (Sandbox Code Playgroud)


小智 6

这是一个 POSIX 函数来执行此操作:

url_encode() {
   awk 'BEGIN {
      for (n = 0; n < 125; n++) {
         m[sprintf("%c", n)] = n
      }
      n = 1
      while (1) {
         s = substr(ARGV[1], n, 1)
         if (s == "") {
            break
         }
         t = s ~ /[[:alnum:]_.!~*\47()-]/ ? t s : t sprintf("%%%02X", m[s])
         n++
      }
      print t
   }' "$1"
}
Run Code Online (Sandbox Code Playgroud)

例子:

value=$(url_encode "$2")
Run Code Online (Sandbox Code Playgroud)


dav*_*ers 5

这是节点版本:

uriencode() {
  node -p "encodeURIComponent('${1//\'/\\\'}')"
}
Run Code Online (Sandbox Code Playgroud)

  • 在页面其他地方找到的这个变体通过从 STDIN 读取值来避免引用问题:`node -p 'encodeURIComponent(require("fs").readFileSync(0))'` (2认同)

小智 5

问题是在bash中执行此操作并且不需要python或perl,因为事实上只有一个命令可以完全按照您的要求运行 - "urlencode".

value=$(urlencode "${2}")
Run Code Online (Sandbox Code Playgroud)

这也好得多,因为例如上面的perl答案没有正确编码所有字符.尝试使用从Word获得的长划线,你得到错误的编码.

注意,您需要安装"gridsite-clients"来提供此命令.

  • 所以你的答案并不比任何需要安装别人的东西好(python,perl,lua,...) (4认同)
  • 我的 bash (GNU 3.2) 版本没有 `urlencode`。你用的是什么版本? (2认同)

Rya*_*yan 5

简单的PHP选项:

echo 'part-that-needs-encoding' | php -R 'echo urlencode($argn);'
Run Code Online (Sandbox Code Playgroud)


nul*_*ght 5

这是我用于嵌入式系统的 busybox ash shell 的版本,我最初采用了 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}"
}
Run Code Online (Sandbox Code Playgroud)


Wol*_*ahl 5

Python 3 基于 @sandro 2010 年的好答案:

echo "Test & /me" | python -c "import urllib.parse;print (urllib.parse.quote(input()))"
Run Code Online (Sandbox Code Playgroud)

测试%20%26%20/我


mas*_*ilo 5

这个基于 nodejs 的答案将在 stdin 上使用encodeURIComponent

uriencode_stdin() {
    node -p 'encodeURIComponent(require("fs").readFileSync(0))'
}

echo -n $'hello\nwörld' | uriencode_stdin
hello%0Aw%C3%B6rld

Run Code Online (Sandbox Code Playgroud)