博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

Ajian的学习天地


简单人生 Simple Life

生存是为了自己。。。。 而生活是为了所有的人。。。。自己快乐就能感染不快乐的人。自己学会快乐也就教会别人快乐。。。。 所以从现在起学会生活,学会快乐。。-----Ajian

  ajian.cublog.cn

关于作者
姓名: Ajian
年龄: 21
职位: 系统工程师
Q Q:  63894624
MSN:  5root@live.cn
mail: 5root@live.cn
   转眼一年过去了,凭着自己的热情和执着,实现了自己不少的愿望,可以慢慢还我欠下的所有的情,其中不枉有很多艰辛也有很多乐趣,新的一年继续加油!A ZA A ZA ^_^
   补充句我的Blog搬家了,新家的地址http://www.AjianZone.cn
|| << >> ||
我的分类


Shell程序集锦七——shell的几个技巧备忘[转载]

1.将你的代码uuencode(gmime-uuencode)进某个shell,然后执行该shell处理完所有的编译操作和模块加载操作,以满足一般用户或windows爱好者的使用习惯。
例子1:
引用

#!/bin/sh
SRC_DIR_NAME='somedevice'
SRC_DIR='somedevice'
TMP_DIR='/tmp'
TGZ_FILE='somedevice.tgz'

if [ "$1" = check ] ; then
       lcnt=`cat $0| wc -l`
       lcnt=`expr $lcnt - 1`
       head -n $lcnt $0 | md5sum
       tail -n 1 $0
       if [ -f $0.md5 ]; then
               cat $0.md5
       fi
       exit 0
fi

output=/dev/null

if [ "$1" != xterm -a "$1" != blind ] ; then
       tty=`ps j $$ | tail -n 1 | awk '{ print $5 }'`
       sid=`ps j $$ | tail -n 1 | awk '{ print $4 }'`
       xsid=`ps j -C X | tail -n 1 | awk '{ print $4 }'`

       echo $tty, $sid, $xsid > $output

       if [ $tty = '?' -o "$sid" = "$xsid" ] ; then

               echo xterm > $output

               if ! xterm -fg black -bg white -g 80x25 -font fixed -e "$0" xterm  > $output 2>&1 ; then
                       (echo ; echo ) | "$0" blind
               fi
               exit 0
       fi
fi

if [ "$1" = "extract" ] ; then
       echo TGZ_FILE=\'$TGZ_FILE\'\; SRC_DIR=\'$SRC_DIR\'\; TMP_DIR=\'$TMP_DIR\'
else
       echo '(*) Extract files from ['$0'] to ['$TMP_DIR/$SRC_DIR_NAME']'
fi
gmime-uudecode "$0"                     || exit 1
cd $TMP_DIR                             || exit 1
tar -xzf "$TGZ_FILE"    || exit 1
cd "$SRC_DIR_NAME"              || exit 1
if [ "$1" = "extract" ] ; then
       exit 0
fi
echo '(*) Start installer ['$TMP_DIR/$SRC_DIR_NAME/setup']'
./setup $* || exit 1

if [ "$1" = xterm ] ; then
       echo
       echo "Press 'Enter' to continue..."
       read tmp
fi

exit 0

begin 644 /tmp/somedevice.tgz
M'XL(`#SF8$```^P[?U/;R)+[K_PI9MF"2,;&LK`)Q"%5Q$`>N^;'&=B8(YQ*
M2#)6L"V?)(-]K+_[=??,2"/9))NW;Z_JZLZ58*FGIZ>GNZ>[IV>
MM9_^OH]I-LRWS29\TZ?X3<]UT]PVZSO6S@[`Z_6&V?B)-?]&GM+/-$Z
MHC!,OH7WO?;_I9]$ZM\+G(>_R0A^0/_;YML&Z-_:KIO_K___B4]>_U9SXCK#
....
M+?=?.X8)RGU=_\V=YL[V3Z#W)B"A"P#\[>;;YD_,_->RL?KS?US_M3)+G/MW
M^5?3PH?GX7EX'IZ'Y^%Y>!Z>A^?A>7@>GH?GX7EX'IZ'Y^%Y>!Z>A^?A>7@>
8GH?GX7EX'IZ'Y^'Y=WW^'S!`]'$`X`L`
`
end
三  4月 25 09:37:01 CST 2007
bc6d7d377f78c7f298bd74a1d12ebf87  -


2.定时切割某个不停增长的日志文件,否则对于大文件,open是件麻烦事情,而且可以每天打包保存,或处理,都有好处。
例子2:
引用
#! /bin/sh
#file: cutsomekindlog.sh
#author: zhengyu
#desc: cut somekindlog and send to somekind
#date: Apr 10 18:50
#version: v1.0
#modify:

#get ip and handle ip
rawip=`/sbin/ifconfig | awk '/inet/{print $2}' | awk -F: 'NR==1{print $2}'`
ip=`echo $rawip|awk -F. '{print $4}'`

#get date and handle date
file_date=`/bin/date +"%y%m%d"`
file_year=`/bin/date +"%y"`
file_moth=`/bin/date +"%m"`
file_mothday=`/bin/date +"%m%d"`

echo "cutsomekindlog.sh start working at `date +%y/%m/%d/%H:%M:%S`" >>/var/log/cutlog/cutsomekindlog.log

filepath=/opt/guess/logs/somekindlog/$file_year/$file_moth/$file_date

#build filepath
mkdir -p $filepath

pushd $filepath

filename=${file_date}.somekindlog.${ip}.log.gz

#create file
/usr/bin/gzip -c /opt/guess/logs/somekindlog/${ip}.log > $filename
>/opt/guess/logs/somekindlog/${ip}.log

#touch $filename

if [ $? -ne 0 ]
then
       echo "gzip did a wrong work at `date +%y/%m/%d/%H:%M:%S`" >>/var/log/cutlog/cutsomekindlog.log
else
       echo "gzip succeed at `date +%y/%m/%d/%H:%M:%S`" >>/var/log/cutlog/cutsomekindlog.log
fi

cp -f $filename ../${file_mothday}.somekindlog.${ip}.gz

echo "created $file_mothday.somekind.log.gz at `date +%y/%m/%d/%H:%M:%S`" >>/var/log/cutlog/cutsomekindlog.log

popd

dirpath=/opt/guess/logs/somekindlog/$file_year/$file_moth/

pushd $dirpath

echo "/usr/bin/rsync -rtu $file_date someip::somemodule at `date +%y/%m/%d/%H:%M:%S`" >>/var/log/cutlog/cutsomekindlog.log

#rsync to service
/usr/bin/rsync -rtu $file_date someip::somemodule >>/var/log/cutlog/cutsomekindlog.log

if [ $? -ne 0 ]
then
       echo "rsync error at `date +%y/%m/%d/%H:%M:%S`" >>/var/log/cutlog/cutsomekindlog.log
else
       echo "rsync succeed at `date +%y/%m/%d/%H:%M:%S`" >>/var/log/cutlog/cutsomekindlog.log
fi

#delete the tmp file
rm -rf $file_date

echo "cutlog.sh finished at `date +%y/%m/%d/%H:%M:%S`" >>/var/log/cutlog/cutsomekindlog.log

popd

#delete file created somedays ago
gzpath=/var/log/somekindlog/

pushd $gzpath

delfile=`du -a|grep ".log.gz"|awk '{print $2}'|sort -nr|tail -n 1`

rm -rf $delfile

if [ $? -ne 0 ]
then
       echo "Waining: $delfile was not delete" >>/var/log/cutlog/cutsomekindlog.log
else
       echo "$delfile was deleted successfully" >>/var/log/cutlog/cutsomekindlog.log
fi

popd

exit 0


3.用sort处理基于文本统计事项。
例子3:
引用
#!/bin/bash
#
#file:
#usage:
#author:
#date:

file_date=`/bin/date +"%y%m%d"`
file_year=`/bin/date +"%y"`
file_moth=`/bin/date +"20%y%m"`
file_mothday=`/bin/date +"%m%d"`

ase_dir=/opt/rcvpool/somekind_log
statics_dir=/opt/rcvpool/somekind_statics
work_dir=/opt/rcvpool/somekind_log/$file_date

pushd $base_dir

for i in *.somekindlog.*.log.gz
do
       gunzip $i
       rm -rf $i
done

for i in *.somekindlog.*.log
do
       for ((j=1;j<8;j++))
       do
               grep "chn1=${j}" $i >>${j}_somekindlog.log
       done
done

for ((i=1;i<8;i++))
do
       sort -t "=" +1 -2 -nr ${i}_somekindlog.log >${i}_sorted.log
       rm -rf ${i}_somekindlog.log
done

for ((i=1;i<8;i++))
do
       awk -F"=|&" 'BEGIN{vid=0;count=0;}
                         {if(NR == 1)
                          {
                               vid = $2;
                               count --;
                          }
                          if(vid == $2)
                          {
                               count ++;
                          }
                          else
                          {
                               count ++;
                               print vid" "count;
                               vid = $2;
                               count = 0;
                          }
                         }
                    END{print vid" "count;}' ${i}_sorted.log |sort +1 +0 -nr >>${i}_result.txt
done

mkdir -p ${statics_dir}/$file_date && mv -f *_result.txt ${statics_dir}/$file_date

exit 0


4.获取前一天的日期,没有必要大动干戈自己写个c代码调用time然后又减去多少多少然后在localtime。直接用date -d "yesterday"等等,另外date对于文件归档有不可代替的作用。
例子4:
引用
#!/bin/bash
#
#file:
#decs:
#usage:
#version:

echo "vd_statics starts at `date +%y/%m/%d/%H:%M:%S`" >>/usr/home/zhengyu/vd_statics.log

file_ym=20`/bin/date -d "yesterday" +"%y%m"`
file_day=`/bin/date -d "yesterday" +"%d"`

#file_ym=20`/bin/date +"%y%m"`
#file_day=`/bin/date +"%d"`

file_path=/opt/rcvpool/vd_log/${file_ym}/${file_day}

file_create_all=vd_create_${file_ym}${file_day}.log
file_visit_all=vd_visit_${file_ym}${file_day}.log

pushd $file_path

sort -m -k3,4 vd_create_*.log_* >${file_create_all} && sort -m -k3,4 vd_visit_*.log_* >${file_visit_all} || (echo "sort error at `date +%y/%m/%d/%H:%M:%S`" >>/usr/home/zhengyu/vd_statics.log && exit 255 )

visit_number=`cat ${file_visit_all} |wc -l`

create_succ=`cat ${file_create_all} |grep create_succ |wc -l`
create_fail=`cat ${file_create_all} |grep create_fail |wc -l`

create_succ_reg=`cat ${file_create_all} |grep "type:reg" |grep create_succ |wc -l`
create_succ_log=`cat ${file_create_all} |grep "type:log" |grep create_succ |wc -l`
create_succ_update=`cat ${file_create_all} |grep "type:update" |grep create_succ |wc -l`

succ_from_reg=`echo "scale=4;$create_succ_reg/$create_succ"|bc`
succ_from_log=`echo "scale=4;$create_succ_log/$create_succ"|bc`
succ_from_update=`echo "scale=4;$create_succ_update/$create_succ"|bc`

cat >>/usr/home/zhengyu/vd_statics.log << EOF

visit_number $visit_number
create_succ $create_succ   reg: $create_succ_reg $succ_from_reg  log: $create_succ_log $succ_from_log  update: $create_succ_update $succ_from_update
create_fail $create_fail

EOF
echo "vd_statics ends at `date +%y/%m/%d/%H:%M:%S`" >>/usr/home/zhengyu/vd_statics.log
echo >>/usr/home/zhengyu/vd_statics.log

echo << EOF

cat << EOF |mail -s "vd_statics `date +%D`" -c zhengyu AT domain.com.cn somebody AT domain.com.cn || echo "mail error" >>/usr/home/zhengyu/vd_statics.log
sit_number $visit_number
create_succ $create_succ   reg: $create_succ_reg $succ_from_reg  log: $create_succ_log $succ_from_log  update: $create_succ_update $succ_from_update
create_fail $create_fail
EOF

popd

exit 0


5.多使用find,强大功能对于归档很有帮助。
例子5:
引用
#!/bin/bash
#
#file:
#usage:
#author:
#date:

file_date=`/bin/date -d "yesterday" +"%y%m%d"`
file_year=`/bin/date -d "yesterday" +"%y"`
file_moth=`/bin/date -d "yesterday" +"20%y%m"`
file_mothday=`/bin/date -d "yesterday" +"%m%d"`

#file_date=`/bin/date +"%y%m%d"`
#file_year=`/bin/date +"%y"`
#file_moth=`/bin/date +"20%y%m"`
#file_mothday=`/bin/date +"%m%d"`

base_dir=/opt/rcvpool/kind_statics
statics_dir=/opt/vreport_data/basekinds/somekind/weekly
work_dir=${base_dir}/${file_date}

pushd $base_dir

list=`awk '{print $1}' /usr/home/zhengyu/shellcode/kind_list.txt`

for i in $list
do
       findv=`find . -ctime -7 -type f|egrep "[0-9]+_daily"|egrep "/${i}_daily.txt"`
       cat `echo $findv`|sort +0 -nr > ${i}_week_sorted.txt
       awk 'BEGIN{vid=0;count=0;}
               {if(NR==1)
                  {
                       vid = $1;
                       count = 0;
                  }
                if(vid == $1)
                  {
                       count += $2;
                  }
                else
                  {
                       if(vid != 0)
                       {
                               print vid" "count;
                       }
                       vid = $1;
                       count = $2;
                  }
               }
            END{if(vid != 0) print vid" "count;}' ${i}_week_sorted.txt |sort +1 +0 -nr >${i}_result.txt
       rm -f ${i}_week_sorted.txt
done

sort -m -k2 -nr *_result.txt >all_weekly.txt

mkdir -p ${statics_dir}/${file_date} && mv -f *_result.txt ${statics_dir}/${file_date} &&  mv -f all_weekly.txt ${statics_dir}/${file_date} && chown -R www.www ${statics_dir}/${file_date}

popd

exit 0


6.用trap+kill触发事件,编写具有magic效应的代码。
例子6:
引用

#!/bin/bash
# Tetris Game
# $Id$
#
# Copyright (C) xhchen
# All rights reserved.
#
# $Log$
#

#颜色定义
cRed=1
cGreen=2
cYellow=3
cBlue=4
cFuchsia=5
cCyan=6
cWhite=7
colorTable=($cRed $cGreen $cYellow $cBlue $cFuchsia $cCyan $cWhite)
#位置和大小
iLeft=3
iTop=2
((iTrayLeft = iLeft + 2))
((iTrayTop = iTop + 1))
((iTrayWidth = 10))
((iTrayHeight = 15))
#颜色设置
cBorder=$cGreen
cScore=$cFuchsia
cScoreValue=$cCyan
#控制信号
#改游戏使用两个进程,一个用于接收输入,一个用于游戏流程和显示界面;
#当前者接收到上下左右等按键时,通过向后者发送signal的方式通知后者。
sigRotate=25
sigLeft=26
sigRight=27
sigDown=28
sigAllDown=29
sigExit=30
#七中不同的方块的定义
#通过旋转,每种方块的显示的样式可能有几种
box0=(0 0 0 1 1 0 1 1)
box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)
box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)
box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)
box4=(0 1 0 2 1 1 2 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 0 1 0 1 1 1 2)
box5=(0 1 1 1 2 1 2 2 1 0 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 0 1 1 1 2)
box6=(0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 1 0 1 1 1 2)
#所有其中方块的定义都放到box变量中
box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})
#各种方块旋转后可能的样式数目
countBox=(1 2 2 2 4 4 4)
#各种方块再box数组中的偏移
offsetBox=(0 1 3 5 7 11 15)
#每提高一个速度级需要积累的分数
iScoreEachLevel=50  #be greater than 7
#运行时数据
sig=0       #接收到的signal
iScore=0    #总分
iLevel=0    #速度级
boxNew=()   #新下落的方块的位置定义
cBoxNew=0   #新下落的方块的颜色
iBoxNewType=0   #新下落的方块的种类
iBoxNewRotate=0 #新下落的方块的旋转角度
boxCur=()   #当前方块的位置定义
cBoxCur=0   #当前方块的颜色
iBoxCurType=0   #当前方块的种类
iBoxCurRotate=0 #当前方块的旋转角度
boxCurX=-1  #当前方块的x坐标位置
boxCurY=-1  #当前方块的y坐标位置
iMap=()     #背景方块图表
#初始化所有背景方块为-1, 表示没有方块
for ((i = 0; i < iTrayHeight * iTrayWidth; i++)); do iMap[$i]=-1; done

#接收输入的进程的主函数
function RunAsKeyReceiver()
{
   local pidDisplayer key aKey sig cESC sTTY
   pidDisplayer=$1
   aKey=(0 0 0)
   cESC=`echo -ne "\33"`
   cSpace=`echo -ne "\40"`
   #保存终端属性。在read -s读取终端键时,终端的属性会被暂时改变。
   #如果在read -s时程序被不幸杀掉,可能会导致终端混乱,
   #需要在程序退出时恢复终端属性。
   sTTY=`stty -g`
   #捕捉退出信号
   trap "MyExit;" INT TERM
   trap "MyExitNoSub;" $sigExit
   #隐藏光标
   echo -ne "\33[?25l"

   while [[ 1 ]]
   do
       #读取输入。注-s不回显,-n读到一个字符立即返回
       read -s -n 1 key
       aKey[0]=${aKey[1]}
       aKey[1]=${aKey[2]}
       aKey[2]=$key
       sig=0
       #判断输入了何种键
       if [[ $key == $cESC && ${aKey[1]} == $cESC ]]
       then
           #ESC键
           MyExit
       elif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]]
       then
           if [[ $key == "A" ]]; then sig=$sigRotate   #<向上键>
           elif [[ $key == "B" ]]; then sig=$sigDown   #<向下键>
           elif [[ $key == "D" ]]; then sig=$sigLeft   #<向左键>
           elif [[ $key == "C" ]]; then sig=$sigRight  #<向右键>
           fi
       elif [[ $key == "W" || $key == "w" ]]; then sig=$sigRotate  #W, w
       elif [[ $key == "S" || $key == "s" ]]; then sig=$sigDown    #S, s
       elif [[ $key == "A" || $key == "a" ]]; then sig=$sigLeft    #A, a
       elif [[ $key == "D" || $key == "d" ]]; then sig=$sigRight   #D, d
       elif [[ "[$key]" == "[]" ]]; then sig=$sigAllDown   #空格键
       elif [[ $key == "Q" || $key == "q" ]]           #Q, q
       then
           MyExit
       fi
       if [[ $sig != 0 ]]
       then
           #向另一进程发送消息
           kill -$sig $pidDisplayer
       fi
   done
}
#退出前的恢复
function MyExitNoSub()
{
   local y
   #恢复终端属性
   stty $sTTY
   ((y = iTop + iTrayHeight + 4))
   #显示光标
   echo -e "\33[?25h\33[${y};0H"
   exit
}

function MyExit()
{
   #通知显示进程需要退出
   kill -$sigExit $pidDisplayer
   MyExitNoSub
}

#处理显示和游戏流程的主函数
function RunAsDisplayer()
{
   local sigThis
   InitDraw
   #挂载各种信号的处理函数
   trap "sig=$sigRotate;" $sigRotate
   trap "sig=$sigLeft;" $sigLeft
   trap "sig=$sigRight;" $sigRight
   trap "sig=$sigDown;" $sigDown
   trap "sig=$sigAllDown;" $sigAllDown
   trap "ShowExit;" $sigExit
   while [[ 1 ]]
   do
       #根据当前的速度级iLevel不同,设定相应的循环的次数
       for ((i = 0; i < 21 - iLevel; i++))
       do
           usleep 20000
           sigThis=$sig
           sig=0
           #根据sig变量判断是否接受到相应的信号
           if ((sigThis == sigRotate)); then BoxRotate;    #旋转
           elif ((sigThis == sigLeft)); then BoxLeft;  #左移一列
           elif ((sigThis == sigRight)); then BoxRight;    #右移一列
           elif ((sigThis == sigDown)); then BoxDown;  #下落一行
           elif ((sigThis == sigAllDown)); then BoxAllDown;    #下落到底
           fi
       done
       #kill -$sigDown $$
       BoxDown #下落一行
   done
}

#BoxMove(y, x), 测试是否可以把移动中的方块移到(x, y)的位置, 返回0则可以, 1不可以
function BoxMove()
{
   local j i x y xTest yTest
   yTest=$1
   xTest=$2
   for ((j = 0; j < 8; j += 2))
   do
       ((i = j + 1))
       ((y = ${boxCur[$j]} + yTest))
       ((x = ${boxCur[$i]} + xTest))
       if (( y < 0 || y >= iTrayHeight || x < 0 || x >= iTrayWidth))
       then
           #撞到墙壁了
           return 1
       fi
       if ((${iMap[y * iTrayWidth + x]} != -1 ))
       then
           #撞到其他已经存在的方块了
           return 1
       fi
   done
   return 0;
}

#将当前移动中的方块放到背景方块中去,
#并计算新的分数和速度级。(即一次方块落到底部)
function Box2Map()
{
   local j i x y xp yp line
   #将当前移动中的方块放到背景方块中去
   for ((j = 0; j < 8; j += 2))
   do
       ((i = j + 1))
       ((y = ${boxCur[$j]} + boxCurY))
       ((x = ${boxCur[$i]} + boxCurX))
       ((i = y * iTrayWidth + x))
       iMap[$i]=$cBoxCur
   done
   #消去可被消去的行
   line=0
   for ((j = 0; j < iTrayWidth * iTrayHeight; j += iTrayWidth))
   do
       for ((i = j + iTrayWidth - 1; i >= j; i--))
       do
           if ((${iMap[$i]} == -1)); then break; fi
       done
       if ((i >= j)); then continue; fi
       ((line++))
       for ((i = j - 1; i >= 0; i--))
       do
           ((x = i + iTrayWidth))
           iMap[$x]=${iMap[$i]}
       done
       for ((i = 0; i < iTrayWidth; i++))
       do
           iMap[$i]=-1
       done
   done
   if ((line == 0)); then return; fi
   #根据消去的行数line计算分数和速度级
   ((x = iLeft + iTrayWidth * 2 + 7))
   ((y = iTop + 11))
   ((iScore += line * 2 - 1))
   #显示新的分数
   echo -ne "\33[1m\33[3${cScoreValue}m\33[${y};${x}H${iScore}         "
   if ((iScore % iScoreEachLevel < line * 2 - 1))
   then
       if ((iLevel < 20))
       then
           ((iLevel++))
           ((y = iTop + 14))
           #显示新的速度级
           echo -ne "\33[3${cScoreValue}m\33[${y};${x}H${iLevel}        "
       fi
   fi
   echo -ne "\33[0m"

   #重新显示背景方块
   for ((y = 0; y < iTrayHeight; y++))
   do
       ((yp = y + iTrayTop + 1))
       ((xp = iTrayLeft + 1))
       ((i = y * iTrayWidth))
       echo -ne "\33[${yp};${xp}H"
       for ((x = 0; x < iTrayWidth; x++))
       do
           ((j = i + x))
           if ((${iMap[$j]} == -1))
           then
               echo -ne "  "
           else
               echo -ne "\33[1m\33[7m\33[3${iMap[$j]}m\33[4${iMap[$j]}m[]\33[0m"
           fi
       done
   done
}

#下落一行
function BoxDown()
{
   local y s
   ((y = boxCurY + 1)) #新的y坐标
   if BoxMove $y $boxCurX  #测试是否可以下落一行
   then
       s="`DrawCurBox 0`"  #将旧的方块抹去
       ((boxCurY = y))
       s="$s`DrawCurBox 1`"    #显示新的下落后方块
       echo -ne $s
   else
       #走到这儿, 如果不能下落了
       Box2Map     #将当前移动中的方块贴到背景方块中
       RandomBox   #产生新的方块
   fi
}
#左移一列
function BoxLeft()
{
   local x s
   ((x = boxCurX - 1))
   if BoxMove $boxCurY $x
   then
       s=`DrawCurBox 0`
       ((boxCurX = x))
       s=$s`DrawCurBox 1`
       echo -ne $s
   fi
}
#右移一列
function BoxRight()
{
   local x s
   ((x = boxCurX + 1))
   if BoxMove $boxCurY $x
   then
       s=`DrawCurBox 0`
       ((boxCurX = x))
       s=$s`DrawCurBox 1`
       echo -ne $s
   fi
}

#下落到底
function BoxAllDown()
{
   local k j i x y iDown s
   iDown=$iTrayHeight
   #计算一共需要下落多少行
   for ((j = 0; j < 8; j += 2))
   do
       ((i = j + 1))
       ((y = ${boxCur[$j]} + boxCurY))
       ((x = ${boxCur[$i]} + boxCurX))
       for ((k = y + 1; k < iTrayHeight; k++))
       do
           ((i = k * iTrayWidth + x))
           if (( ${iMap[$i]} != -1)); then break; fi
       done
       ((k -= y + 1))
       if (( $iDown > $k )); then iDown=$k; fi
   done
   s=`DrawCurBox 0`    #将旧的方块抹去
   ((boxCurY += iDown))
   s=$s`DrawCurBox 1`  #显示新的下落后的方块
   echo -ne $s
   Box2Map     #将当前移动中的方块贴到背景方块中
   RandomBox   #产生新的方块
}

#旋转方块
function BoxRotate()
{
   local iCount iTestRotate boxTest j i s
   iCount=${countBox[$iBoxCurType]}    #当前的方块经旋转可以产生的样式的数目
   #计算旋转后的新的样式
   ((iTestRotate = iBoxCurRotate + 1))
   if ((iTestRotate >= iCount))
   then
       ((iTestRotate = 0))
   fi
   #更新到新的样式, 保存老的样式(但不显示)
   for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++))
   do
       boxTest[$j]=${boxCur[$j]}
       boxCur[$j]=${box[$i]}
   done
   if BoxMove $boxCurY $boxCurX    #测试旋转后是否有空间放的下
   then
       #抹去旧的方块
       for ((j = 0; j < 8; j++))
       do
           boxCur[$j]=${boxTest[$j]}
       done
       s=`DrawCurBox 0`
       #画上新的方块
       for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++))
       do
           boxCur[$j]=${box[$i]}
       done
       s=$s`DrawCurBox 1`
       echo -ne $s
       iBoxCurRotate=$iTestRotate
   else
       #不能旋转,还是继续使用老的样式
       for ((j = 0; j < 8; j++))
       do
           boxCur[$j]=${boxTest[$j]}
       done
   fi
}

#DrawCurBox(bDraw), 绘制当前移动中的方块, bDraw为1, 画上, bDraw为0, 抹去方块。
function DrawCurBox()
{
   local i j t bDraw sBox s
   bDraw=$1
   s=""
   if (( bDraw == 0 ))
   then
       sBox="\40\40"
   else
       sBox="[]"
       s=$s"\33[1m\33[7m\33[3${cBoxCur}m\33[4${cBoxCur}m"
   fi
   for ((j = 0; j < 8; j += 2))
   do
       ((i = iTrayTop + 1 + ${boxCur[$j]} + boxCurY))
       ((t = iTrayLeft + 1 + 2 * (boxCurX + ${boxCur[$j + 1]})))
       #\33[y;xH, 光标到(x, y)处
       s=$s"\33[${i};${t}H${sBox}"
   done
   s=$s"\33[0m"
   echo -n $s
}

#更新新的方块
function RandomBox()
{
   local i j t
   #更新当前移动的方块
   iBoxCurType=${iBoxNewType}
   iBoxCurRotate=${iBoxNewRotate}
   cBoxCur=${cBoxNew}
   for ((j = 0; j < ${#boxNew[@]}; j++))
   do
       boxCur[$j]=${boxNew[$j]}
   done

   #显示当前移动的方块
   if (( ${#boxCur[@]} == 8 ))
   then
       #计算当前方块该从顶端哪一行"冒"出来
       for ((j = 0, t = 4; j < 8; j += 2))
       do
           if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi
       done
       ((boxCurY = -t))
       for ((j = 1, i = -4, t = 20; j < 8; j += 2))
       do
           if ((${boxCur[$j]} > i)); then i=${boxCur[$j]}; fi
           if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi
       done
       ((boxCurX = (iTrayWidth - 1 - i - t) / 2))
       #显示当前移动的方块
       echo -ne `DrawCurBox 1`
       #如果方块一出来就没处放,Game over!
       if ! BoxMove $boxCurY $boxCurX
       then
           kill -$sigExit ${PPID}
           ShowExit
       fi
   fi

   #清除右边预显示的方块
   for ((j = 0; j < 4; j++))
   do
       ((i = iTop + 1 + j))
       ((t = iLeft + 2 * iTrayWidth + 7))
       echo -ne "\33[${i};${t}H        "
   done
   #随机产生新的方块
   ((iBoxNewType = RANDOM % ${#offsetBox[@]}))
   ((iBoxNewRotate = RANDOM % ${countBox[$iBoxNewType]}))
   for ((j = 0, i = (${offsetBox[$iBoxNewType]} + $iBoxNewRotate) * 8; j < 8; j++, i++))
   do
       boxNew[$j]=${box[$i]};
   done
   ((cBoxNew = ${colorTable[RANDOM % ${#colorTable[@]}]}))
   #显示右边预显示的方块
   echo -ne "\33[1m\33[7m\33[3${cBoxNew}m\33[4${cBoxNew}m"
   for ((j = 0; j < 8; j += 2))
   do
       ((i = iTop + 1 + ${boxNew[$j]}))
       ((t = iLeft + 2 * iTrayWidth + 7 + 2 * ${boxNew[$j + 1]}))
       echo -ne "\33[${i};${t}H[]"
   done
   echo -ne "\33[0m"
}

#初始绘制
function InitDraw()
{
   clear
   RandomBox   #随机产生方块,这时右边预显示窗口中有方快了
   RandomBox   #再随机产生方块,右边预显示窗口中的方块被更新,原先的方块将开始下落
   local i t1 t2 t3
   #显示边框
   echo -ne "\33[1m"
   echo -ne "\33[3${cBorder}m\33[4${cBorder}m"
   ((t2 = iLeft + 1))
   ((t3 = iLeft + iTrayWidth * 2 + 3))
   for ((i = 0; i < iTrayHeight; i++))
   do
       ((t1 = i + iTop + 2))
       echo -ne "\33[${t1};${t2}H||"
       echo -ne "\33[${t1};${t3}H||"
   done
   ((t2 = iTop + iTrayHeight + 2))
   for ((i = 0; i < iTrayWidth + 2; i++))
   do
       ((t1 = i * 2 + iLeft + 1))
       echo -ne "\33[${iTrayTop};${t1}H=="
       echo -ne "\33[${t2};${t1}H=="
   done
   echo -ne "\33[0m"

   #显示"Score"和"Level"字样
   echo -ne "\33[1m"
   ((t1 = iLeft + iTrayWidth * 2 + 7))
   ((t2 = iTop + 10))
   echo -ne "\33[3${cScore}m\33[${t2};${t1}HScore"
   ((t2 = iTop + 11))
   echo -ne "\33[3${cScoreValue}m\33[${t2};${t1}H${iScore}"
   ((t2 = iTop + 13))
   echo -ne "\33[3${cScore}m\33[${t2};${t1}HLevel"
   ((t2 = iTop + 14))
   echo -ne "\33[3${cScoreValue}m\33[${t2};${t1}H${iLevel}"
   echo -ne "\33[0m"
}

#退出时显示GameOVer!
function ShowExit()
{
   local y
   ((y = iTrayHeight + iTrayTop + 3))
   echo -e "\33[${y};0HGameOver!\33[0m"
   exit
}

#游戏主程序在这儿开始.
if [[ $1 != "--show" ]]
then
   sh $0 --show&   #以参数--show将本程序再运行一遍
   RunAsKeyReceiver $! #以上一行产生的进程的进程号作为参数
   exit
else
   #当发现具有参数--show时,运行显示函数
   RunAsDisplayer
   exit
fi


7.here document的妙用,用于互动的命令行工具,如fdisk,vi等等。
例子7:
引用
vi test.log << EOF
:%s/something/otherthing/g
:x
EOF


例子没有分析了,反正每个都实现一个功能,权且做template吧,下次碰见了在dereference了。
最后需要探究的是,虽然shell没有参数类型一说,但是cpp泛型算法的思路还是值得学习的,比如对于某个参数相同或相似的命令。呵呵,大概是学cpp学晕了,才学三天就找不着北了。

 原文地址 shell的几个技巧备忘
发表于: 2008-01-07,修改于: 2008-01-07 09:13,已浏览322次,有评论0条 推荐 投诉


网友评论
 发表评论