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
来检查你所拥有的版本.
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)
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在评论中所建议的那样.谢谢!
jos*_*sch 63
为了完整起见,许多解决方案使用sed
或awk
仅翻译一组特殊字符,因此代码大小非常大,也不会翻译应编码的其他特殊字符.
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是使用hexdump
Debian中的bsdmainutils 包.根据下图,bsdmainutils和vim-common应该具有大致相同的安装可能性:
但是在这里使用的版本hexdump
代替xxd
并允许避免tr
调用:
echo -ne 'some random\nbytes' | hexdump -v -e '/1 "%02x"' | sed 's/\(..\)/%\1/g'
Run Code Online (Sandbox Code Playgroud)
小智 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)
小智 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)
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)
blu*_*yed 30
我发现以下代码片段可用于将其粘贴到程序调用链中,其中可能未安装URI :: Escape:
perl -p -e 's/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg'
Run Code Online (Sandbox Code Playgroud)
(来源)
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)
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认为它会把它变成空格
这是一个不调用任何外部程序的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)
对于那些寻找不需要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)
从网上的几个地方缝合在一起并进行一些本地试验和错误.它很棒!
在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)
什么能比 JavaScript 更好地解析 URL?
node -p "encodeURIComponent('$url')"
Run Code Online (Sandbox Code Playgroud)
如果您不想依赖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)
uni2ascii非常方便:
$ echo -ne '????' | uni2ascii -aJ
%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C
Run Code Online (Sandbox Code Playgroud)
你可以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)
这是节点版本:
uriencode() {
node -p "encodeURIComponent('${1//\'/\\\'}')"
}
Run Code Online (Sandbox Code Playgroud)
小智 5
问题是在bash中执行此操作并且不需要python或perl,因为事实上只有一个命令可以完全按照您的要求运行 - "urlencode".
value=$(urlencode "${2}")
Run Code Online (Sandbox Code Playgroud)
这也好得多,因为例如上面的perl答案没有正确编码所有字符.尝试使用从Word获得的长划线,你得到错误的编码.
注意,您需要安装"gridsite-clients"来提供此命令.
简单的PHP选项:
echo 'part-that-needs-encoding' | php -R 'echo urlencode($argn);'
Run Code Online (Sandbox Code Playgroud)
这是我用于嵌入式系统的 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)
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/我
这个基于 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)
归档时间: |
|
查看次数: |
304099 次 |
最近记录: |