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

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

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


评论

另请参阅:如何在Shell中解码URL编码的字符串?用于非卷曲解决方案。

另请参阅:如何在命令行上编码和解码百分比编码的字符串?

#1 楼

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


此发布数据,类似于其他--data选项,不同之处在于它执行URL编码。为了符合CGI,<data>部件应以名称开头,后跟分隔符和内容规范。


示例用法:

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


有关更多信息,请参见手册页。

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

您还可以对查询字符串进行编码:

curl -G \
    --data-urlencode "p1=value 1" \
    --data-urlencode "p2=value 2" \
    http://example.com
    # http://example.com?p1=value%201&p2=value%202


评论


似乎仅适用于HTTP POST。此处的文档:curl.haxx.se/docs/manpage.html#--data-urlencode

–斯坦·詹姆斯(Stan James)
2012年4月13日下午6:47

@StanJames如果像这样使用它,curl也可以对GET请求进行编码。 curl -G --data-urlencode“ blah = df ssdf sdf” –data-urlencode“ blah2 = dfsdf sdfsd” http://whatever.com/whatever

–kberg
2012年5月7日20:52



@kberg实际上,这仅适用于查询数据。 curl会附加一个“?”其次是urlencoded参数。如果您要对某些网址后缀进行urlencode(例如某些文档ID的CouchDB GET),则'--data-urlencode'将不起作用。

–散景
2012年8月28日在22:41



不适合curl --data-urlencode“ description =![image]($ url)” www.example.com。知道为什么吗? `

–Khurshid Alam
16 Jun 3'20:37



@NadavB转义“‽

– BlackJack
18年4月19日在9:33

#2 楼

这是纯BASH答案。

rawurlencode() {
  local string=""
  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()函数,该函数-非常谦虚-很棒。现在可以执行一些简单测试:文件等)。我在OpenWRT路由器上发现了此问题。
# 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
}


评论


不幸的是,该脚本在某些字符上失败,例如“é”和“ 1/2”,分别输出“ e%FFFFFFFFFFFFFFFFCC”和“%FFFFFFFFFFFFFFC2”(我相信每个字符循环的b / c)。

–数学
2014年3月24日17:13

它在Bash 4.3.11(1)中对我不起作用。字符串Jogging«àl'Hèze»生成Jogging%20%abà%20l%27Hèze%bb,无法将其馈送到JS解码URIComponent :(

– dmcontador
2015年11月19日在12:07

在第一段代码中,printf的最后一个参数是什么意思?也就是说,为什么要使用双引号,单引号,美元符号,字母c和双引号?单引号可以吗?

– Colin Fraizer
16年5月19日在14:31

@dmcontador-这只是一个不起眼的bash脚本,没有多字节字符或unicode的概念。当它看到像ń(\ u0144)这样的字符时,它将天真地输出%144 ,,(\ u2561)将输出为%2561。正确的原始ururlencoded答案分别是%C5%84%0A和%E2%95%A1。

–嗜尿菌
16年6月8日在9:49

@ Matthematics,@ dmcontador,@ Orwellophile:我之前的评论是错误的。使用xxd的解决方案更有效,并且在任何情况下(对于任何字符)都可以使用。我已经更新了我的脚本。无论如何,看来rawurldecode()函数的表现异常出色。 :)

–tukusejssirs
19-10-13在21:42

#3 楼

另一个选择是使用jq
 $ printf %s 'encode this'|jq -sRr @uri
encode%20this
$ jq -rn --arg x 'encode this' '$x|@uri'
encode%20this
 

-r--raw-output)输出字符串的原始内容,而不是JSON字符串文字。 -n--null-input)不能从STDIN读取输入。如果您的输入仅包含一行,或者您不想将换行符替换为-R,则可以用--raw-input替换-sR
或将此百分比编码为所有字节:
 --slurp --raw-input 


评论


<3它...应该是顶级且被接受的IMO(是的,如果您可以告诉curl进行编码,并且bash具有可以接受的内置函数-但jq似乎是合适的选择,但我距离获得舒适感还很远这个工具的水平)

– nhed
17年11月16日16:16



对于任何想和我一样的人:@uri不是变量,而是用于格式化字符串和转义的文字jq过滤器;有关详细信息,请参见jq手册(对不起,没有直接链接,需要在页面上搜索@uri ...)

–ssc
18年7月13日在11:48

xxd版本只是我一直在寻找的那种东西。即使有点脏,它也很短而且没有依赖性

–瑞安·桑德森(Rian Sanderson)
18年11月21日在15:08

jq到url编码的示例用法:printf“ http:// localhost:8082 /” | jq -sRr'@uri'

–阿舒托什·金达尔(Ashutosh Jindal)
19年8月7日在21:57



我认为这不是最佳答案的唯一原因是因为OP专门询问了curl。如果curl可以单独完成,您就不会循环使用第二个工具jq。但是,这是一个很棒的通用实用程序,可通过脚本或命令行将输出通过管道传输到。

–詹姆森
12月9日19:16

#4 楼

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

评论


URI :: Escape可能未安装,请检查我的答案。

–蓝色
09年11月10日19:50

我修复了此问题(使用echo,pipe和<>),现在即使$ 2包含撇号或双引号,它也可以工作。谢谢!

–dubek
2010年1月3日,9:35

您也可以取消echo:value =“ $(perl -MURI :: Escape -e'print uri_escape($ ARGV [0]);'” $ 2“)”

–克里斯·约翰森(Chris Johnsen)
2010年1月3日,10:31

克里斯·约翰森的版本更好。我在测试表达式中有$ {True},并通过回显使用了它,使uri_escape / Perl变量扩展跳了起来。

–mm2001
2010年1月7日在16:35

@ jrw32982是的,回头看一下,用另一种语言可以完成此任务是好的。如果可以的话,我会收回我的选票,但可惜它目前已锁定。

–thecoshman
14年8月26日在18:36

#5 楼

为了完整起见,许多使用sedawk的解决方案仅翻译一组特殊字符,因此在代码大小上相当大,并且不翻译其他应编码的特殊字符。

一种安全的方法urlencode只是对每个单个字节进行编码-即使是允许的字节也是如此。不是字符。

编辑:

xxd在Debian中带有vim-common软件包,而我只是在未安装它的系统上,所以我不想安装它。替代方法是使用Debian中bsdmainutils软件包中的hexdump。根据下图,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' | xxd -plain | tr -d '\n' | sed 's/\(..\)/%/g'


评论


xxd -plain应该在tr -d'\ n'之后发生!

– qdii
2012年7月8日在16:24



@qdii为什么?这不仅使无法对换行符进行urlencode,而且还会错误地将xxd创建的换行符插入输出。

– josch
2012年7月14日在16:26

@josch。这是完全错误的。首先,任何\ 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结尾的某些字符串,使其不适合用户。您可以添加-n回显来解决它。

– qdii
2012年7月14日在22:49



@qdii实际上-n缺少回显,但是xxd调用属于tr -d调用的前面。它属于此处,因此foobar中的任何换行符都由xxd翻译。 xxd调用后的tr -d是删除xxd产生的换行符。似乎您永远没有足够长的foobar来使xxd产生换行符,但是对于长输入而言,它将如此。因此,tr -d是必需的。与您的假设相反,tr -d不是从输入中删除换行符,而是从xxd输出中删除换行符。我想在输入中保留换行符。您唯一有效的一点是,该回显会添加不必要的换行符。

– josch
2012年7月20日在9:44



@qdii且没有冒犯-我只是认为您是错的,但回声-n确实不见了

– josch
2012年7月20日9:53



#6 楼

变体之一可能很丑陋,但很简单:



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


例如,这是单线版本(如Bruno所建议的):

评论


我认为这是重用cURL的URL编码的非常聪明的方法。

–solidsnack
2012年10月24日15:17

这绝对是太棒了!我真希望您将其保留为一行,以便人们可以看到它的真实程度。若要对日期命令的结果进行URL编码…date | curl -Gso / dev / null -w%{url_effective} --data-urlencode @-“” | cut -c 3-(您必须删掉前2个字符,因为curl的输出在技术上是带有查询字符串的相对URL。)

–布鲁诺·布鲁诺斯基(Bruno Bronosky)
13-3-2在3:07



@BrunoBronosky您的单线变体很好,但似乎在编码末尾添加了“%0A”。用户要当心。函数版本似乎没有此问题。

–浏览器
16年8月10日在17:25

为避免最后出现%0A,请使用printf而不是echo。

– Kenorb
18年5月2日,0:11



一个班轮很棒

–斯蒂芬·布鲁姆(Stephen Blum)
18年8月30日在23:31

#7 楼

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

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


Triple'确保值中的单引号不会受到伤害。 urllib在标准库中。它适用于这种疯狂的(现实世界)网址:

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


评论


我在使用引号和特殊字符使用三引号时遇到了一些麻烦,这似乎基本上适用于所有内容:encode_value =“ $(echo -n” $ {data}“ | python -c” import urllib; import sys; sys.stdout。 write(urllib.quote(sys.stdin.read()))“)”;

–停止莫妮卡·赛利奥(Monica Cellio)
2011年11月14日14:33

Python 3版本将为encode_value = $(python3 -c“ import urllib.parse; print(urllib.parse.quote('''$ value'''))”))。

–Creshal
13年10月10日,11:33



python -c'导入urllib,sys; sys.stdout.writelines(sys.stdin中l的urllib.quote_plus(l,safe =“ / \ n”))'几乎没有引用问题,并且应该具有内存/速度效率(未选中,另存为斜眼) )

–阿洛瓦·马哈德(Alois Mahdal)
2015年11月7日在5:19



引用sys.argv而不是将$ value替换为稍后解析为代码的字符串会更加安全。如果值包含'''+ __import __(“ os”)。system(“ rm -rf〜”)+'''怎么办?

–查尔斯·达菲(Charles Duffy)
16年5月18日在20:45



python -c“ import urllib; print urllib.quote(raw_input())” <<<“ $ data”

– Rockallite
17年2月9日在8:02



#8 楼

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

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


(源)

评论


为我工作。我将其更改为perl -lpe ...(字母ell)。这删除了结尾的换行符,这是我需要的。

–JohnnyLambada
2012年10月17日18:52

仅供参考,要执行相反的操作,请使用perl -pe's / \%(\ w \ w)/ chr hex $ 1 / ge'(来源:unix.stackexchange.com/questions/159253/…)

– Sridhar Sarnobat
2015年11月10日19:46



根据具体需要编码的字符,可以将其简化为perl -pe's /(\ W)/ sprintf(“ %%% 02X”,ord($ 1))/ ge',允许字母,数字和下划线,但编码其他所有内容。

– robru
16 Mar 4 '16 at 9:30

感谢您以上的回复!由于用例是针对curl的:也就是说::和/不需要编码,因此我在bashrc / zshrc中的最终功能是:perl -lpe's /([[A-Za-z0-9。\ /:] )/ sprintf(“ %%% 02X”,ord($ 1))/ seg

–范
12月16日4:32



#9 楼

如果您希望运行GET请求并使用纯卷曲,只需将--get添加到@Jacob的解决方案中。

这里是一个示例:

#10 楼

这可能是最好的之一:

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


评论


这对我有用,有两个附加功能:1.用-n替换-e以避免在参数末尾添加换行符;并且2.在printf字符串中添加'%%'以在每个字符串对的前面放置%十六进制数字。

–罗布·法根(Rob Fagen)
16-5-3在23:26



在将$前面的括号添加到$ =(echo -e ...

–罗马·罗恩·内斯特罗夫
16年9月1日在8:22

请解释这是如何工作的。 od命令并不常见。

–马克·斯托斯伯格
18-11-19在0:47

这不适用于OS X的od,因为它使用的输出格式与GNU od不同。例如printf aa | od -An -tx1 -v | tr \-打印----------- 61--61 ------------------ --------------------------------------使用OS X的od和-61-61使用GNU的od 。您可以将od -An -tx1 -v | sed's / * / / g; s / * $ //'| tr \%| tr -d \\ n与OS X的od或GNU od一起使用。 xxd -p | sed's /../%&/ g'| tr -d \\ n也做同样的事情,即使xxd不在POSIX中,而od是。

– nisetama
19年1月8日,11:59



尽管这可能有效,但它会转义每个字符

–查理
19-10-14在8:25

#11 楼

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


评论


是否有获取UTF-8编码而不是ASCII的简单变体?

–avgvstvs
2015年10月2日,16:16

#12 楼

这是一个不调用任何外部程序的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"
}


评论


bash版本之间的行为有所不同。在RHEL 6.9上,bash为4.1.2,其中包括单引号。 Debian 9和bash 4.4.12可以使用单引号。对我来说,删除单引号会使它同时起作用。 s =“ $ {s //','/%2C}”

–安东·克鲁格(Anton Krug)
18年5月23日在15:28



我更新了答案以反映您的发现,@ muni764。

– davidchambers
18年5月23日在21:01

只是警告...这不会编码字符á

–diogovk
4月27日19:27

#13 楼

url=$(echo "" | 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内的字符串进行编码并将其输出到$ url中。即使您愿意,也不必将其放在var中。 BTW并未包含sed for选项卡,因为它会把它变成空格

评论


我觉得这不是推荐的方法。

–科迪·格雷♦
2011年1月11日下午13:27

请解释一下您的感觉...。因为我所说的有效,并且已在多个脚本中使用了它,所以我知道它适用于列出的所有字符。因此,请解释为什么有人不使用我的代码并使用perl,因为其标题是“来自bash脚本的URLEncode”而不是perl脚本。

– manoflinux
2011-2-8在2:55



有时不需要珍珠溶液,因此可以派上用场

– Yuval Rimar
2011年10月31日在11:31

不建议这样做,因为黑名单是一种不好的做法,而且对unicode还是不利的。

– Ekevoo
2011-12-20 14:16

这是与cat file.txt兼容的最友好的解决方案

–mrwaim
18年1月20日在19:51

#14 楼

从外壳程序脚本使用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"



http://www.php.net/manual/en/function.rawurlencode.php
http://www.php.net/manual/zh/function.rawurldecode.php


#15 楼

对于那些正在寻找不需要perl的解决方案的人,这里只需要hexdump和awk:

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

 encodedurl="";

 # 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 '
      == "20"                    { printf("%s",   "+"); next } # space becomes plus
      ~  /0[adAD]/               {                      next } # strip newlines
      ~  /^[a-zA-Z0-9.*()\/-]$/  { printf("%s",   );  next } # pass through what we can
                                   { printf("%%%s", )        } # take hex value of everything else
   '`
}


从几个地方缝在一起网络和一些本地试验和错误。效果很好!

#16 楼

uni2ascii非常方便:

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


评论


这对于ASCII范围内需要引用的字符不起作用,例如%和空格(最后一个可以用-s标志纠正)

– Boldewyn
13年2月7日在14:59

#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


source

#18 楼

您可以在perl中模拟javascript的encodeURIComponent。这是命令:

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


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

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


现在您可以通过管道插入encodeURIComponent

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


#19 楼

这是节点版本:

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


评论


如果字符串中还有其他在单引号之间引起无效的字符(例如单反斜杠或换行符),是否不会中断?

– Stuart P. Bentley
16年12月31日在19:09

好点子。如果我们要在Bash中转义所有有问题的字符,那么我们不妨直接执行替换操作并完全避免节点。我发布了仅Bash的解决方案。 :)

– davidchambers
17年1月1日,下午2:46

在页面其他地方找到的此变体通过从STDIN读取值来避免引用问题:node -p'encodeURIComponent(require(“ fs”)。readFileSync(0))'

–马克·斯托斯伯格
18年11月19日在1:02

#20 楼

简单的PHP选项:

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


#21 楼

问题是关于在bash中执行此操作,并且不需要python或perl,因为实际上只有一个命令可以完全满足您的要求-“ urlencode”。

value=$(urlencode "")


这样也更好,例如,上面的perl答案不能正确编码所有字符。尝试使用从Word获得的长破折号,并且编码错误。

请注意,您需要安装“ gridsite-clients”才能提供此命令。

评论


我的bash版本(GNU 3.2)没有urlencode。您使用什么版本?

– Sridhar Sarnobat
2015年11月10日19:27

我有4.3.42,但是urlencode命令由“ gridsite-clients”提供。尝试安装它,应该没问题。

–迪伦
15年11月12日在12:45

因此,您的答案并不比要求安装其他任何东西(python,perl,lua等)的要好。

–西里尔·庞特维
17年7月27日在7:36

除了只需要安装一个实用程序而不是安装整个语言(和库)外,另外,它非常简单明了,可以看到它在做什么。

–迪伦
17年7月28日在13:29

首先,提供此命令的软件包/项目页面的链接将很有用。

– Doron Behar
3月27日10:26

#22 楼

Ruby,出于完整性考虑

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


#23 楼

另一个php方法:

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


评论


echo将附加一个换行符(十六进制0xa)。要停止它,请使用echo -n。

–马修堂
2014年10月10日上午10:01

#24 楼

这是执行此操作的POSIX函数:

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


示例:

value=$(encodeURIComponent "")




#25 楼

这是我用于嵌入式系统的busybox灰壳的版本,我最初采用了Orwellophile的变体:

urlencode()
{
    local S=""
    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}"
}


#26 楼

这是使用Lua的单行转换,类似于blueyed的答案,除了所有RFC 3986未保留字符未编码(如此答案)之外:

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


此外,您可以需要确保将字符串中的换行符从LF转换为CRLF,在这种情况下,可以在百分比编码之前的链中插入gsub("\r?\n", "\r\n")

这是一种变体,非标准样式的application / x-www-form-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 - "")


#27 楼

Python 3基于@sandro从2010年以来的好答案:
echo "Test & /me" | python -c "import urllib.parse;print (urllib.parse.quote(input()))"

测试%20%26%20 / me

#28 楼

安装了php后,我使用这种方式:

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


#29 楼

这是orwellophile答案的ksh版本,其中包含rawurlencode和rawurldecode函数(链接:如何为curl命令对数据进行urlencode?)。我没有足够的代表来发表评论,因此没有新评论。.

#!/bin/ksh93

function rawurlencode
{
    typeset string=""
    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++


#30 楼

什么比URL解析URL更好?

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


评论


超出操作问题范围。不重击,不卷曲。即使我确定节点可用也能很好地工作。

–西里尔·庞特维
17年7月27日在7:32

为什么要对此投票而不是python / perl答案?此外,这如何不响应原始问题“如何为curl命令添加数据?”。可以从bash脚本中使用它,并将结果提供给curl命令。

– Nestor Urquiza
17年7月31日在11:54

我也否决了其他人。问题是如何在bash脚本中执行此操作。如果使用其他语言(例如node / js,python或perl),则无需直接使用curl。

–西里尔·庞特维
17年8月3日在14:35

尽管我不费吹灰之力,但是此命令的问题在于它需要正确地转义数据才能在javascript中使用。像尝试使用单引号和一些反斜杠疯狂一样。如果要使用节点,则最好从stdin中读取内容,例如节点-p'encodeURIComponent(require(“ fs”)。readFileSync(0))'

– Michael Krelin-黑客
18年1月6日在18:01

如果要从STDIN传递数据,请谨慎使用@ MichaelKrelin-hacker的解决方案,请确保不要包含结尾的换行符。例如,echo | ...是错误的,而echo -n | ...取消换行符。

–马克·斯托斯伯格
18年11月19日,0:57