用shell进行ASCII字符转换与URL编码技巧
lipiwang 2025-05-24 15:21 1 浏览 0 评论
如何将ASCII字符转换为十进制(或十六进制)值并进行相反的转换?如何进行URL编码和URL解码?
如果你在编写脚本时已知八进制或十六进制值,你可以使用printf命令实现:
# POSIX
printf '\047\n'
# bash/ksh/zsh 和其他一些 printf 实现也支持:
printf '\x27\n'
在字符编码为ASCII的超集的地区,这将打印出单引号字符(47是撇号字符的八进制ASCII值),后面是一个换行符。十六进制版本也可以在包括bash内置在内的一些printf实现中使用,但不是标准的/POSIX的。
在bash 4.2及更高版本以及ksh93中,printf还支持Unicode代码点:
# bash 4.2, ksh93
printf '\u0027\n'
另一种方法是使用bash的#39;...'引用方法来扩展所需的字符,可以用于变量赋值或直接作为命令参数:
ExpandedString=#39;\x27\047\u0027\U00000027\n'
printf %s\\n "$ExpandedString"
# 或者更简单地
printf %s\\n #39;\x27\047\u0027\U00000027\n'
如果你需要对事先未知的字符(或数字ASCII值)进行转换(即在变量中),可以使用稍微复杂一些的方法。注意:这些函数仅适用于单字节字符编码。
# POSIX
# chr() - 将十进制值转换为ASCII字符表示
# ord() - 将ASCII字符转换为其十进制值
chr() {
[ "$1" -lt 256 ] || return 1
printf "\\$(printf %o "$1")"
}
为了避免使用子shell,更好的方法是将值传递给变量而不是命令输出。这样更快,因为它避免了子shell的使用。
chr () {
local val
[ "$1" -lt 256 ] || return 1
printf -v val %o "$1"; printf "\\$val"
# 需要bash 3.1或更高版本。
}
ord() {
# POSIX
LC_CTYPE=C printf %d "'$1"
}
# hex() - 将ASCII字符转换为十六进制值
# unhex() - 将十六进制值转换为ASCII字符
hex() {
LC_CTYPE=C printf %x "'$1"
}
unhex() {
printf "\\x$1"
}
# 示例:
chr "$(ord A)" # -> A
ord "$(chr 65)" # -> 65
上述的ord函数相当巧妙。
巧妙?更确切地说,它使用了一个我无法在任何地方找到文档的特性 - 在字符前面加上单引号。这是一个很不错的效果,但你是怎么知道它的呢?是源码挖掘吗?- GreyCat
它符合Single Unix规范:“如果前导字符是单引号或双引号,则值应为在单引号或双引号之后的字符的底层代码集中的数值。”(参见 printf() 了解更多)- mjf
URL编码和URL解码
请注意,URL编码仅在字节(八位)级别上定义。对多字节(例如UTF-8)字符进行URL编码仅需要对每个字节进行单独编码,然后将其连接起来。
还请注意,下面的urldecode函数不执行错误检查。如果输入的数据不正确,如何生成有意义的错误消息是留给读者的练习。
urlencode() {
# urlencode <string>
local LC_ALL=C c i n
for (( i = 0, n = ${#1}; i < n; i++ )); do
c=${1:i:1}
case $c in
[[:alnum:].~_-]) printf %s "$c" ;;
*) printf %%%02X "'$c" ;;
esac
done
}
urldecode() {
# urldecode <string>
local s
s=${1//\\/\\\\}
s=${s//+/ }
printf %b "${s//'%'/\\x}"
}
# 或者使用另一种urlencode方式,一次性打印所有字符(需要bash 3.1)
urlencode() {
# urlencode <string>
local LC_ALL=C c i n=${#1}
local out= tmp
for (( i=0; i < n; i++ )); do
c=${1:i:1}
case $c in
[[:alnum:].~_-]) printf -v tmp %s "$c" ;;
*) printf -v tmp %%%02X "'$c" ;;
esac
out+=$tmp
done
printf %s "$out"
}
更完整的示例(带有UTF-8支持)
命令行实用程序nkf可以解码URL:
echo 'https://ja.wikipedia.org/wiki/%E9%87%8E%E8%89%AF%E7%8C%AB' | nkf --url-input
关于扩展ASCII和UTF-8编码的注意事项
以下示例从未经过同行评审。每个人都对它感到恐惧。请自行决定是否继续。
- 对于值0x00 - 0x7f,结果相同。
- 对于值0x80 - 0xff,UTF-8和扩展ASCII之间有冲突。
- 对于值0x100 - 0xffff,只能是UTF-8、UTF-16和UTF-32。
- 对于值0x100 - 0x7FFFFFFF,只能是UTF-8和UTF-32。
数值 | EAscii | UTF-8 | UTF-16 | UTF-32 |
0x20 | "\x20" | "\x20" | \u0020 | \U00000020 |
0x20 | "\x7f" | "\x7f" | \u007f | \U0000007f |
0x80 | "\x80" | "\xc2\x80" | \u0080 | \U00000080 |
0xff | "\xff" | "\xc3\xbf" | \u00ff | \U000000ff |
0x100 | N/A | "\xc4\x80" | \u0100 | \U00000100 |
0x1000 | N/A | "\xc8\x80" | \u1000 | \U00001000 |
0xffff | N/A | "\xef\xbf\xbf" | \uffff | \U0000ffff |
0x10000 | N/A | "\xf0\x90\x80\x80" | \ud800\udc00 | \U00010000 |
0xfffff | N/A | "\xf3\xbf\xbf\xbf" | \udbbf\udfff | \U000fffff |
0x10000000 | N/A | "\xfc\x90\x80\x80\x80\x80" | N/A | \U10000000 |
0x7fffffff | N/A | "\xfd\xbf\xbf\xbf\xbf\xbf" | N/A | \U7fffffff |
0x80000000 | N/A | N/A | N/A | N/A |
0xffffffff | N/A | N/A | N/A | N/A |
###########################################################################
## ord family
###########################################################################
# ord <返回变量名称> <要转换的字符> [可选格式字符串]
# ord_hex <返回变量名称> <要转换的字符>
# ord_oct <返回变量名称> <要转换的字符>
# ord_utf8 <返回变量名称> <要转换的字符> [可选格式字符串]
# ord_eascii <返回变量名称> <要转换的字符> [可选格式字符串]
# ord_echo <要转换的字符> [可选格式字符串]
# ord_hex_echo <要转换的字符>
# ord_oct_echo <要转换的字符>
# ord_utf8_echo <要转换的字符> [可选格式字符串]
# ord_eascii_echo <要转换的字符> [可选格式字符串]
#
# 描述:
# 将使用本地编码的字符转换为十进制值,并存储在指定的变量中。
# 将其存储在指定的变量中
#
# ord
# ord_hex 以十六进制输出
# ord_oct 以八进制输出
# ord_utf8 强制使用UTF8解码
# ord_eascii 强制使用eascii解码
# ord_echo 输出到标准输出流(stdout)
# ord_hex_echo 以十六进制输出并输出到标准输出流(stdout)
# ord_oct_echo 以八进制输出并输出到标准输出流(stdout)
# ord_utf8_echo 强制使用UTF8解码并输出到标准输出流(stdout)
# ord_eascii_echo 强制使用eascii解码并输出到标准输出流(stdout)
function ord {
printf -v "${1?Missing Dest Variable}" "${3:-%d}" "'${2?Missing Char}"
}
function ord_oct {
ord "${@:1:2}" "0%c"
}
function ord_hex {
ord "${@:1:2}" "0x%x"
}
function ord_utf8 {
LC_CTYPE=C.UTF-8 ord "${@}"
}
function ord_eascii {
LC_CTYPE=C ord "${@}"
}
function ord_echo {
printf "${2:-%d}" "'${1?Missing Char}"
}
function ord_oct_echo {
ord_echo "${1}" "0%o"
}
function ord_hex_echo {
ord_echo "${1}" "0x%x"
}
function ord_utf8_echo {
LC_CTYPE=C.UTF-8 ord_echo "${@}"
}
function ord_eascii_echo {
LC_CTYPE=C ord_echo "${@}"
}
###########################################################################
## chr family
###########################################################################
# chr_utf8 <返回变量名称> <要转换的整数>
# chr_eascii <返回变量名称> <要转换的整数>
# chr <返回变量名称> <要转换的整数>
# chr_oct <返回变量名称> <要转换的八进制数>
# chr_hex <返回变量名称> <要转换的十六进制数>
# chr_utf8_echo <要转换的整数>
# chr_eascii_echo <要转换的整数>
# chr_echo <要转换的整数>
# chr_oct_echo <要转换的八进制数>
# chr_hex_echo <要转换的十六进制数>
#
# 描述:
# 将十进制值转换为字符表示,并将其存储在指定的变量中
#
# chr 尝试猜测输出格式
# chr_utf8 强制使用UTF8编码
# chr_eascii 强制使用eascii编码
# chr_echo 输出到标准输出流(stdout)
#
function chr_utf8_m {
local val
#
# bash仅从4.2版本开始支持\u \U
# 下面是一个如何编码的示例
# 手动
# 自Bash 3.1起,它使用-v选项进行了改进
#
if [[ ${2:?Missing Ordinal Value} -le 0x7f ]]; then
printf -v val "\\%03o" "${2}"
elif [[ ${2} -le 0x7ff ]]; then
printf -v val "\\%03o" \
$(( (${2}>> 6) |0xc0 )) \
$(( ( ${2} &0x3f)|0x80 ))
elif [[ ${2} -le 0xffff ]]; then
printf -v val "\\%03o" \
$(( ( ${2}>>12) |0xe0 )) \
$(( ((${2}>> 6)&0x3f)|0x80 )) \
$(( ( ${2} &0x3f)|0x80 ))
elif [[ ${2} -le 0x1fffff ]]; then
printf -v val "\\%03o" \
$(( ( ${2}>>18) |0xf0 )) \
$(( ((${2}>>12)&0x3f)|0x80 )) \
$(( ((${2}>> 6)&0x3f)|0x80 )) \
$(( ( ${2} &0x3f)|0x80 ))
elif [[ ${2} -le 0x3ffffff ]]; then
printf -v val "\\%03o" \
$(( ( ${2}>>24) |0xf8 )) \
$(( ((${2}>>18)&0x3f)|0x80 )) \
$(( ((${2}>>12)&0x3f)|0x80 )) \
$(( ((${2}>> 6)&0x3f)|0x80 )) \
$(( ( ${2} &0x3f)|0x80 ))
elif [[ ${2} -le 0x7fffffff ]]; then
printf -v val "\\%03o" \
$(( ( ${2}>>30) |0xfc )) \
$(( ((${2}>>24)&0x3f)|0x80 )) \
$(( ((${2}>>18)&0x3f)|0x80 )) \
$(( ((${2}>>12)&0x3f)|0x80 )) \
$(( ((${2}>> 6)&0x3f)|0x80 )) \
$(( ( ${2} &0x3f)|0x80 ))
else
printf -v "${1:?Missing Dest Variable}" ""
return 1
fi
printf -v "${1:?Missing Dest Variable}" "${val}"
}
function chr_utf8 {
local val
[[ ${2?Missing Ordinal Value} -lt 0x80000000 ]] || return 1
if [[ ${2} -lt 0x100 && ${2} -ge 0x80 ]]; then
# bash 4.2 编码错误
# \U000000ff as \xff so encode manually
printf -v val "\\%03o\%03o" $(( (${2}>>6)|0xc0 )) $(( (${2}&0x3f)|0x80 ))
else
printf -v val '\\U%08x' "${2}"
fi
printf -v ${1?Missing Dest Variable} ${val}
}
function chr_eascii {
local val
# 确保值小于0x100
# 否则我们会得到
# \xVVNNNNN
# 其中\xVV = char && NNNNN是一个数字字符串
# 所以chr "0x44321" => "D321"
[[ ${2?Missing Ordinal Value} -lt 0x100 ]] || return 1
printf -v val '\\x%02x' "${2}"
printf -v ${1?Missing Dest Variable} ${val}
}
function chr {
if [ "${LC_CTYPE:-${LC_ALL:-}}" = "C" ]; then
chr_eascii "${@}"
else
chr_utf8 "${@}"
fi
}
function chr_dec {
# 去除前导的0,否则被解释为八进制
chr "${1}" "${2#${2%%[!0]*}}"
}
function chr_oct {
chr "${1}" "0${2}"
}
function chr_hex {
chr "${1}" "0x${2#0x}"
}
function chr_utf8_echo {
local val
[[ ${1?Missing Ordinal Value} -lt 0x80000000 ]] || return 1
if [[ ${1} -lt 0x100 && ${1} -ge 0x80 ]]; then
# bash 4.2 编码错误
# \U000000ff as \xff so encode manually
printf -v val '\\%03o\\%03o' $(( (${1}>>6)|0xc0 )) $(( (${1}&0x3f)|0x80 ))
else
printf -v val '\\U%08x' "${1}"
fi
printf "${val}"
}
function chr_eascii_echo {
local val
# 确保值小于0x100
# 否则我们会得到
# \xVVNNNNN
# 其中\xVV = char && NNNNN是一个数字字符串
# so chr "0x44321" => "D321"
[[ ${1?Missing Ordinal Value} -lt 0x100 ]] || return 1
printf -v val '\\x%x' "${1}"
printf "${val}"
}
function chr_echo {
if [ "${LC_CTYPE:-${LC_ALL:-}}" = "C" ]; then
chr_eascii_echo "${@}"
else
chr_utf8_echo "${@}"
fi
}
function chr_dec_echo {
# 去除前导的0,
# 否则被解释为八进制
chr_echo "${1#${1%%[!0]*}}"
}
function chr_oct_echo {
chr_echo "0${1}"
}
function chr_hex_echo {
chr_echo "0x${1#0x}"
}
#
# 简单的验证码
#
function test_echo_func {
local Outcome _result
_result="$( "${1}" "${2}" )"
[ "${_result}" = "${3}" ] && Outcome="Pass" || Outcome="Fail"
printf "# %-20s %-6s => " "${1}" "${2}" "${_result}" "${3}"
printf "[ "%16q" = "%-16q"%-5s ] " "${_result}" "${3}" "(${3//[[:cntrl:]]/_})"
printf "%s\n" "${Outcome}"
}
function test_value_func {
local Outcome _result
"${1}" _result "${2}"
[ "${_result}" = "${3}" ] && Outcome="Pass" || Outcome="Fail"
printf "# %-20s %-6s => " "${1}" "${2}" "${_result}" "${3}"
printf "[ "%16q" = "%-16q"%-5s ] " "${_result}" "${3}" "(${3//[[:cntrl:]]/_})"
printf "%s\n" "${Outcome}"
}
test_echo_func chr_echo "$(ord_echo "A")" "A"
test_echo_func ord_echo "$(chr_echo "65")" "65"
test_echo_func chr_echo "$(ord_echo ""o")" ""o"
test_value_func chr "$(ord_echo "A")" "A"
test_value_func ord "$(chr_echo "65")" "65"
test_value_func chr "$(ord_echo ""o")" ""o"
# chr_echo 65 => [ A = A (A) ] Pass
# ord_echo A => [ 65 = 65 (65) ] Pass
# chr_echo 246 => [ #39;\303\266' = #39;\303\266' ("o) ] Pass
# chr 65 => [ A = A (A) ] Pass
# ord A => [ 65 = 65 (65) ] Pass
# chr 246 => [ #39;\303\266' = #39;\303\266' ("o) ] Pass
#
test_echo_func chr_echo "65" A
test_echo_func chr_echo "065" 5
test_echo_func chr_dec_echo "065" A
test_echo_func chr_oct_echo "65" 5
test_echo_func chr_hex_echo "65" e
test_value_func chr "65" A
test_value_func chr "065" 5
test_value_func chr_dec "065" A
test_value_func chr_oct "65" 5
test_value_func chr_hex "65" e
# chr_echo 65 => [ A = A (A) ] Pass
# chr_echo 065 => [ 5 = 5 (5) ] Pass
# chr_dec_echo 065 => [ A = A (A) ] Pass
# chr_oct_echo 65 => [ 5 = 5 (5) ] Pass
# chr_hex_echo 65 => [ e = e (e) ] Pass
# chr 65 => [ A = A (A) ] Pass
# chr 065 => [ 5 = 5 (5) ] Pass
# chr_dec 065 => [ A = A (A) ] Pass
# chr_oct 65 => [ 5 = 5 (5) ] Pass
# chr_hex 65 => [ e = e (e) ] Pass
#test_value_func chr 0xff #39;\xff'
test_value_func chr_eascii 0xff #39;\xff'
test_value_func chr_utf8 0xff #39;\uff' # Note this fails because bash encodes it incorrectly
test_value_func chr_utf8 0xff #39;\303\277'
test_value_func chr_utf8 0x100 #39;\u100'
test_value_func chr_utf8 0x1000 #39;\u1000'
test_value_func chr_utf8 0xffff #39;\uffff'
# chr_eascii 0xff => [ #39;\377' = #39;\377' () ] Pass
# chr_utf8 0xff => [ #39;\303\277' = #39;\377' () ] Fail
# chr_utf8 0xff => [ #39;\303\277' = #39;\303\277' ("y) ] Pass
# chr_utf8 0x100 => [ #39;\304\200' = #39;\304\200' (A) ] Pass
# chr_utf8 0x1000 => [ #39;\341\200\200' = #39;\341\200\200' () ] Pass
# chr_utf8 0xffff => [ #39;\357\277\277' = #39;\357\277\277' () ] Pass
test_value_func ord_utf8 "A" 65
test_value_func ord_utf8 ""a" 228
test_value_func ord_utf8 #39;\303\277' 255
test_value_func ord_utf8 #39;\u100' 256
#########################################################
# 用于帮助调试问题的代码段
#########################################################
printf "%q\n" #39;\xff' # => #39;\377'
printf "%q\n" #39;\uffff' # => #39;\357\277\277'
printf "%q\n" "$(chr_utf8_echo 0x100)" # => #39;\304\200'
#
# 这对诊断问题有很大帮助
# 读取或 xterm 程序的输出结果
# 我经常在出错情况下使用它来创建人类可读的错误信息
# 例如:
echo "Enter type to test, Enter to continue"
while read -srN1 ; do
ord asciiValue "${REPLY}"
case "${asciiValue}" in
10) echo "Goodbye" ; break ;;
20|21|22) echo "Yay expected input" ;;
*) printf ':( Unexpected Input 0x%02x %q "%s"\n' "${asciiValue}" "${REPLY}" "${REPLY//[[:cntrl:]]}" ;;
esac
done
#########################################################
# 更奇特的方法 1
#########################################################
# 在发现 LC_CTYPE=C 方法之前,我曾经使用过这种方法
# printf "EAsciiLookup=%q" "$(for (( x=0x0; x<0x100 ; x++)); do printf '%b' $(printf '\\x%02x' "$x"); done)"
EAsciiLookup=#39;\001\002\003\004\005\006\a\b\t\n\v\f\r\016\017\020\021\022\023'
EAsciiLookup+=#39;\024\025\026\027\030\031\032\E\034\035\036\037 !"#$%&\'()*+,-'
EAsciiLookup+=#39;./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghi'
EAsciiLookup+=#39;jklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210'
EAsciiLookup+=#39;\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227'
EAsciiLookup+=#39;\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246'
EAsciiLookup+=#39;\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265'
EAsciiLookup+=#39;\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304'
EAsciiLookup+=#39;\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323'
EAsciiLookup+=#39;\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342'
EAsciiLookup+=#39;\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361'
EAsciiLookup+=#39;\362\363\364\365\366\367\370\371\372\373\374\375\376\377'
function ord_eascii2 {
local idx="${EAsciiLookup%%${2:0:1}*}"
eval ${1}'=$(( ${#idx} +1 ))'
}
#########################################################
# 更奇特的方法 2
#########################################################
#printf "EAsciiLookup2=(\n %s\n)" "$(for (( x=0x1; x<0x100 ; x++)); do printf '%-18s' "$(printf '[_%q]="0x%02x"' "$(printf "%b" "$(printf '\\x%02x' "$x")")" $x )" ; [ "$(($x%6))" != "0" ] || echo -en "\n " ; done)"
typeset -A EAsciiLookup2
EAsciiLookup2=(
[_#39;\001']="0x01" [_#39;\002']="0x02" [_#39;\003']="0x03" [_#39;\004']="0x04"
[_#39;\005']="0x05" [_#39;\006']="0x06" [_#39;\a']="0x07" [_#39;\b']="0x08"
[_#39;\t']="0x09" [_'']="0x0a" [_#39;\v']="0x0b" [_#39;\f']="0x0c"
[_#39;\r']="0x0d" [_#39;\016']="0x0e" [_#39;\017']="0x0f" [_#39;\020']="0x10"
[_#39;\021']="0x11" [_#39;\022']="0x12" [_#39;\023']="0x13" [_#39;\024']="0x14"
[_#39;\025']="0x15" [_#39;\026']="0x16" [_#39;\027']="0x17" [_#39;\030']="0x18"
[_#39;\031']="0x19" [_#39;\032']="0x1a" [_#39;\E']="0x1b" [_#39;\034']="0x1c"
[_#39;\035']="0x1d" [_#39;\036']="0x1e" [_#39;\037']="0x1f" [_\ ]="0x20"
[_\!]="0x21" [_\"]="0x22" [_\#]="0x23" [_\$]="0x24"
[_%]="0x25" [_\&]="0x26" [_\']="0x27" [_\(]="0x28"
[_\)]="0x29" [_\*]="0x2a" [_+]="0x2b" [_\,]="0x2c"
[_-]="0x2d" [_.]="0x2e" [_/]="0x2f" [_0]="0x30"
[_1]="0x31" [_2]="0x32" [_3]="0x33" [_4]="0x34"
[_5]="0x35" [_6]="0x36" [_7]="0x37" [_8]="0x38"
[_9]="0x39" [_:]="0x3a" [_\;]="0x3b" [_\<]="0x3c"
[_=]="0x3d" [_\>]="0x3e" [_\?]="0x3f" [_@]="0x40"
[_A]="0x41" [_B]="0x42" [_C]="0x43" [_D]="0x44"
[_E]="0x45" [_F]="0x46" [_G]="0x47" [_H]="0x48"
[_I]="0x49" [_J]="0x4a" [_K]="0x4b" [_L]="0x4c"
[_M]="0x4d" [_N]="0x4e" [_O]="0x4f" [_P]="0x50"
[_Q]="0x51" [_R]="0x52" [_S]="0x53" [_T]="0x54"
[_U]="0x55" [_V]="0x56" [_W]="0x57" [_X]="0x58"
[_Y]="0x59" [_Z]="0x5a" [_\[]="0x5b" #[_\\]="0x5c"
#[_\]]="0x5d"
[_\^]="0x5e" [__]="0x5f" [_\`]="0x60"
[_a]="0x61" [_b]="0x62" [_c]="0x63" [_d]="0x64"
[_e]="0x65" [_f]="0x66" [_g]="0x67" [_h]="0x68"
[_i]="0x69" [_j]="0x6a" [_k]="0x6b" [_l]="0x6c"
[_m]="0x6d" [_n]="0x6e" [_o]="0x6f" [_p]="0x70"
[_q]="0x71" [_r]="0x72" [_s]="0x73" [_t]="0x74"
[_u]="0x75" [_v]="0x76" [_w]="0x77" [_x]="0x78"
[_y]="0x79" [_z]="0x7a" [_\{]="0x7b" [_\|]="0x7c"
[_\}]="0x7d" [_~]="0x7e" [_#39;\177']="0x7f" [_#39;\200']="0x80"
[_#39;\201']="0x81" [_#39;\202']="0x82" [_#39;\203']="0x83" [_#39;\204']="0x84"
[_#39;\205']="0x85" [_#39;\206']="0x86" [_#39;\207']="0x87" [_#39;\210']="0x88"
[_#39;\211']="0x89" [_#39;\212']="0x8a" [_#39;\213']="0x8b" [_#39;\214']="0x8c"
[_#39;\215']="0x8d" [_#39;\216']="0x8e" [_#39;\217']="0x8f" [_#39;\220']="0x90"
[_#39;\221']="0x91" [_#39;\222']="0x92" [_#39;\223']="0x93" [_#39;\224']="0x94"
[_#39;\225']="0x95" [_#39;\226']="0x96" [_#39;\227']="0x97" [_#39;\230']="0x98"
[_#39;\231']="0x99" [_#39;\232']="0x9a" [_#39;\233']="0x9b" [_#39;\234']="0x9c"
[_#39;\235']="0x9d" [_#39;\236']="0x9e" [_#39;\237']="0x9f" [_#39;\240']="0xa0"
[_#39;\241']="0xa1" [_#39;\242']="0xa2" [_#39;\243']="0xa3" [_#39;\244']="0xa4"
[_#39;\245']="0xa5" [_#39;\246']="0xa6" [_#39;\247']="0xa7" [_#39;\250']="0xa8"
[_#39;\251']="0xa9" [_#39;\252']="0xaa" [_#39;\253']="0xab" [_#39;\254']="0xac"
[_#39;\255']="0xad" [_#39;\256']="0xae" [_#39;\257']="0xaf" [_#39;\260']="0xb0"
[_#39;\261']="0xb1" [_#39;\262']="0xb2" [_#39;\263']="0xb3" [_#39;\264']="0xb4"
[_#39;\265']="0xb5" [_#39;\266']="0xb6" [_#39;\267']="0xb7" [_#39;\270']="0xb8"
[_#39;\271']="0xb9" [_#39;\272']="0xba" [_#39;\273']="0xbb" [_#39;\274']="0xbc"
[_#39;\275']="0xbd" [_#39;\276']="0xbe" [_#39;\277']="0xbf" [_#39;\300']="0xc0"
[_#39;\301']="0xc1" [_#39;\302']="0xc2" [_#39;\303']="0xc3" [_#39;\304']="0xc4"
[_#39;\305']="0xc5" [_#39;\306']="0xc6" [_#39;\307']="0xc7" [_#39;\310']="0xc8"
[_#39;\311']="0xc9" [_#39;\312']="0xca" [_#39;\313']="0xcb" [_#39;\314']="0xcc"
[_#39;\315']="0xcd" [_#39;\316']="0xce" [_#39;\317']="0xcf" [_#39;\320']="0xd0"
[_#39;\321']="0xd1" [_#39;\322']="0xd2" [_#39;\323']="0xd3" [_#39;\324']="0xd4"
[_#39;\325']="0xd5" [_#39;\326']="0xd6" [_#39;\327']="0xd7" [_#39;\330']="0xd8"
[_#39;\331']="0xd9" [_#39;\332']="0xda" [_#39;\333']="0xdb" [_#39;\334']="0xdc"
[_#39;\335']="0xdd" [_#39;\336']="0xde" [_#39;\337']="0xdf" [_#39;\340']="0xe0"
[_#39;\341']="0xe1" [_#39;\342']="0xe2" [_#39;\343']="0xe3" [_#39;\344']="0xe4"
[_#39;\345']="0xe5" [_#39;\346']="0xe6" [_#39;\347']="0xe7" [_#39;\350']="0xe8"
[_#39;\351']="0xe9" [_#39;\352']="0xea" [_#39;\353']="0xeb" [_#39;\354']="0xec"
[_#39;\355']="0xed" [_#39;\356']="0xee" [_#39;\357']="0xef" [_#39;\360']="0xf0"
[_#39;\361']="0xf1" [_#39;\362']="0xf2" [_#39;\363']="0xf3" [_#39;\364']="0xf4"
[_#39;\365']="0xf5" [_#39;\366']="0xf6" [_#39;\367']="0xf7" [_#39;\370']="0xf8"
[_#39;\371']="0xf9" [_#39;\372']="0xfa" [_#39;\373']="0xfb" [_#39;\374']="0xfc"
[_#39;\375']="0xfd" [_#39;\376']="0xfe" [_#39;\377']="0xff"
)
function ord_eascii3 {
local -i val="${EAsciiLookup2["_${2:0:1}"]-}"
if [ "${val}" -eq 0 ]; then
case "${2:0:1}" in
]) val=0x5d ;;
\\) val=0x5c ;;
esac
fi
eval "${1}"'="${val}"'
}
# 为了好玩,请看以下内容
time for (( i=0 ; i <1000; i++ )); do ord TmpVar 'a'; done
# real 0m0.065s
# user 0m0.048s
# sys 0m0.000s
time for (( i=0 ; i <1000; i++ )); do ord_eascii TmpVar 'a'; done
# real 0m0.239s
# user 0m0.188s
# sys 0m0.000s
time for (( i=0 ; i <1000; i++ )); do ord_utf8 TmpVar 'a'; done
# real 0m0.225s
# user 0m0.180s
# sys 0m0.000s
time for (( i=0 ; i <1000; i++ )); do ord_eascii2 TmpVar 'a'; done
# real 0m1.507s
# user 0m1.056s
# sys 0m0.012s
time for (( i=0 ; i <1000; i++ )); do ord_eascii3 TmpVar 'a'; done
# real 0m0.147s
# user 0m0.120s
# sys 0m0.000s
time for (( i=0 ; i <1000; i++ )); do ord_echo 'a' >/dev/null ; done
# real 0m0.065s
# user 0m0.044s
# sys 0m0.016s
time for (( i=0 ; i <1000; i++ )); do ord_eascii_echo 'a' >/dev/null ; done
# real 0m0.089s
# user 0m0.068s
# sys 0m0.008s
time for (( i=0 ; i <1000; i++ )); do ord_utf8_echo 'a' >/dev/null ; done
# real 0m0.226s
# user 0m0.172s
# sys 0m0.012s
更多
了解更多shell的更多编程技巧和编程最佳实践,可以关注我正在编写的《shell脚本编程最佳实践》。
相关推荐
- httpclient+jsoup实现小说线上采集阅读
-
前言 用过老版本UC看小说的同学都知道,当年版权问题比较松懈,我们可以再UC搜索不同来源的小说,并且阅读,那么它是怎么做的呢?下面让我们自己实现一个小说线上采集阅读。(说明:仅用于技术学习、研究) ...
- Python3+requests+unittest接口自动化测试实战
-
一、Requests介绍RequestsisanelegantandsimpleHTTPlibraryforPython,builtforhumanbeings.翻译过来就是...
- 授权码 + PKCE 模式|OIDC & OAuth2.0 认证协议最佳实践系列【03】
-
在上一篇文章中,我们介绍了OIDC授权码模式,本次我们将重点围绕授权码+PKCE模式(AuthorizationCodeWithPKCE)进行介绍,从而让你的系统快速具备接入用户认...
- JWT 在 Java Web 开发中的奇妙应用
-
JWT在JavaWeb开发中的奇妙应用在当今的互联网世界里,安全始终是一个绕不开的话题。而当我们谈论到Web应用的安全性时,认证和授权绝对是其中的核心部分。说到这,我忍不住要给大家讲个笑话...
- 动手操作:一个 OAuth 2 应用程序(2) - 配置 Keycloak 为授权服务器
-
接上一篇《动手操作:一个OAuth2应用程序(1)-应用程序场景》进行场景分析后,本篇就开始动手实现授权服务器。在本文中,我们将Keycloak配置为系统的授权服务器(图3)。...
- JSON Web Token是什么?
-
JSONWebToken(缩写JWT)是目前最流行的跨域认证解决方案。传统的session认证http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证...
- Keycloak Servlet Filter Adapter使用
-
KeycloakClientAdapters简介Keycloakclientadaptersarelibrariesthatmakeitveryeasytosecurea...
- 使用JWT生成token
-
一、使用JWT进行身份验证1、传统用户身份验证Internet服务无法与用户身份验证分开。一般过程如下:用户向服务器发送用户名和密码。验证服务器后,相关数据(如用户角色,登录时间等)将保存在当前会话中...
- 在word中通过VBA调用百度翻译API在线翻译
-
一天的时间,借助各种AI终于解决了这个问题:在word中通过VBA调用百度翻译API进行在线翻译。给我的word又添加了一项神技。先上代码:Sub宏5()''宏5宏Dimapp...
- API 安全之认证鉴权
-
作者:半天前言API作为企业的重要数字资源,在给企业带来巨大便利的同时也带来了新的安全问题,一旦被攻击可能导致数据泄漏重大安全问题,从而给企业的业务发展带来极大的安全风险。正是在这样的背景下,Ope...
- 用WordPress建站哪些插件会拖慢速度影响排名?
-
你是否发现网站加载总慢半拍,SEO排名死活上不去?八成是插件惹的祸!80%的站长不知道,WordPress插件用错类型或配置不当,分分钟让网站速度暴跌,爬虫抓取效率直接砍半。缓存插件没装对,越用越卡你...
- JavaScript报错了?不要慌!怎么看怎么处理都在这里
-
在开发中,有时,我们花了几个小时写的JS代码,在游览器调试一看,控制台一堆红,瞬间一万头草泥马奔腾而来。至此,本文主要记录JS常见的一些报错类型,以及常见的报错信息,分析其报错原因,并给予处理...
-
- 跨站脚本攻击(四)
-
04XSS漏洞挖掘技巧4.1常见的绕过姿势实际应用中web程序往往会通过一些过滤规则来阻止带有恶意代码的用户输入被显示,但由于HTML语言的松散性和各种标签的不同优先级,使得我们绕过过滤规则成为了可能。4.1.1利用大小写绕过HTML标签...
-
2025-05-24 15:21 lipiwang
- WAF-Bypass之SQL注入绕过思路总结
-
过WAF(针对云WAF)寻找真实IP(源站)绕过如果流量都没有经过WAF,WAF当然无法拦截攻击请求。当前多数云WAF架构,例如百度云加速、阿里云盾等,通过更改DNS解析,把流量引入WAF集群,流量经...
- Springboot之登录模块探索(含Token,验证码,网络安全等知识)
-
简介登录模块很简单,前端发送账号密码的表单,后端接收验证后即可~淦!可是我想多了,于是有了以下几个问题(里面还包含网络安全问题):1.登录时的验证码2.自动登录的实现3.怎么维护前后端登录状态在这和大...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- maven镜像 (69)
- undefined reference to (60)
- zip格式 (63)
- oracle over (62)
- date_format函数用法 (67)
- 在线代理服务器 (60)
- shell 字符串比较 (74)
- x509证书 (61)
- localhost (65)
- java.awt.headless (66)
- syn_sent (64)
- settings.xml (59)
- 弹出窗口 (56)
- applicationcontextaware (72)
- my.cnf (73)
- httpsession (62)
- pkcs7 (62)
- session cookie (63)
- java 生成uuid (58)
- could not initialize class (58)
- beanpropertyrowmapper (58)
- word空格下划线不显示 (73)
- jar文件 (60)
- jsp内置对象 (58)
- makefile编写规则 (58)