用shell进行ASCII字符转换与URL编码技巧
如何将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 "ö")" "ö"
test_value_func chr "$(ord_echo "A")" "A"
test_value_func ord "$(chr_echo "65")" "65"
test_value_func chr "$(ord_echo "ö")" "ö"
# chr_echo 65 => [ A = A (A) ] Pass
# ord_echo A => [ 65 = 65 (65) ] Pass
# chr_echo 246 => [ #39;\303\266' = #39;\303\266' (ö) ] Pass
# chr 65 => [ A = A (A) ] Pass
# ord A => [ 65 = 65 (65) ] Pass
# chr 246 => [ #39;\303\266' = #39;\303\266' (ö) ] 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' (ÿ) ] Pass
# chr_utf8 0x100 => [ #39;\304\200' = #39;\304\200' (Ā) ] 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 "ä" 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脚本编程最佳实践》。
请先 后发表评论~