還記得以前那個用算素數的Regex嗎?編程這個世界太有趣了,總是能看到一些即別出心裁的東西。你有沒有想過在寫Shell指令碼的時候可以把你的變數和函數放到一個類中?不要以為這不可能,這不,我在網上又看到了一個把Shell指令碼整成物件導向的東西。Shell本來是不支援的,需要自己做點東西,能搞出這個事事的人真的是hacker啊。
當然,這裡並不是真正的物件導向,因為其只是封裝罷了,還沒有支援繼承和多態。最變態的是他居然還支援typeid,靠!
下面讓我們看看他是怎麼來做的。下面的指令碼可能會有點費解。本想解釋一下,後來想想,還是大家自己專研一下吧,其實看懂也不難,給大家提幾個點吧。
我們可以看到,下面的這個指令碼定義了class, func, var, new 等函數,其實這些就是所謂的關鍵字。
class是一個函數,主要是記錄類名。
func和var實際上是把成員函數名和成員變數記成有相同首碼的各種變數。
new方法主要是記錄執行個體。大家重點看看new函數裡的那個for迴圈,最核心的就在那裡了。
指令碼如下所示:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 #!/bin/bash # ------------------------------------------------------------------- # OO support functions # Kludged by Pim van Riezen <pi@madscience.nl> # ------------------------------------------------------------------- DEFCLASS=""CLASS=""THIS=0 class() { DEFCLASS="$1" eval CLASS_${DEFCLASS}_VARS="" eval CLASS_${DEFCLASS}_FUNCTIONS=""} static() { return 0 } func() { local varname="CLASS_${DEFCLASS}_FUNCTIONS" eval "$varname=\"\${$varname}$1 \""} var() { local varname="CLASS_${DEFCLASS}_VARS" eval $varname="\"\${$varname}$1 \""} loadvar() { eval "varlist=\"\$CLASS_${CLASS}_VARS\"" for var in $varlist; do eval "$var=\"\$INSTANCE_${THIS}_$var\"" done} loadfunc() { eval "funclist=\"\$CLASS_${CLASS}_FUNCTIONS\"" for func in $funclist; do eval "${func}() { ${CLASS}::${func} \"\$*\"; return \$?; }" done} savevar() { eval "varlist=\"\$CLASS_${CLASS}_VARS\"" for var in $varlist; do eval "INSTANCE_${THIS}_$var=\"\$$var\"" done} typeof() { eval echo \$TYPEOF_$1 } new() { local local cvar="$2" shift shift local id=$(uuidgen | tr A-F a-f | sed -e "s/-//g") eval TYPEOF_${id}=$class eval $cvar=$id local funclist eval "funclist=\"\$CLASS_${class}_FUNCTIONS\"" for func in $funclist; do eval "${cvar}.${func}() { local t=\$THIS; THIS=$id; local c=\$CLASS; CLASS=$class; loadvar; loadfunc; ${class}::${func} \"\$*\"; rt=\$?; savevar; CLASS=\$c; THIS=\$t; return $rt; }" done eval "${cvar}.${class} \"\$*\" || true"}
下面,讓我們來看看常式吧。
123456789101112131415161718192021222324252627282930313233343536373839404142 # ------------------------------------------------------------------- # Example code # ------------------------------------------------------------------- # class definition class Storpel func Storpel func setName func setQuality func print var name var quality # class implementation Storpel::Storpel() { setName "$1" setQuality "$2" if [ -z "$name" ]; then setName "Generic"; fi if [ -z "$quality" ]; then setQuality "Normal"; fi} Storpel::setName() { name="$1"; } Storpel::setQuality() { quality="$1"; } Storpel::print() { echo "$name ($quality)"; } # usage new Storpel one "Storpilator 1000" Medium new Storpel two new Storpel three two.setName "Storpilator 2000"two.setQuality "Strong" one.print two.print three.print echo "" echo "one: $one ($(typeof $one))"echo "two: $two ($(typeof $two))"echo "three: $three ($(typeof $two))"
(全文完)