首页 电脑 电脑学堂 查看内容

感受一下完美的shell编写规范

2011-8-9 12:17 953 0

摘要:   最近24花了不少时间在研究shell,对于这个东西也学了挺久了,一些基本的需要都能够写出来,但是超过几百行甚至上千行的代码都是没写过。在阿里巴巴这段时间一直在研究好几个长达上千行的shell脚本,...
关键词: nbsp 脚本 代码 ECHO ESC Function shell stty Mine GameExit

  最近24花了不少时间在研究shell,对于这个东西也学了挺久了,一些基本的需要都能够写出来,但是超过几百行甚至上千行的代码都是没写过。在阿里巴巴这段时间一直在研究好几个长达上千行的shell脚本,实际上里头存在很多类似的调用,比如说函数。再者就是对整个硬件体系的深入了解,摸清楚系统的工作原理和流程,但怎么说能够写出功能如此强悍的代码,24还是钦佩不已。  接下来这周24主要还是研究awk这部分,应该说shell的内容主要围绕一些循环、判断、获取用户数据、显示数据、函数、脚本控制之类的内容展开,以及借用grep、sed、awk、cut、sort、正则表达式等等之类的实现具体的需求。总的来说,awk显得较为强大,几乎可以取代了其他脚本实现方法。这段时间24在51CTO论坛里开了个帖子专门探究shell脚本编程:Shell脚本编程置顶贴(源源不断)大家有兴趣都可以去捧捧场,学习学习。里头有一个ID为wenmin88888 都用awk实现了,基本上都是一条命令搞定。换成sed 附带if判断之类的恐怕要写很长了。  说到代码规范,其实每个程序员都很关注这一点,只是换成系统管理员来说就没那么重视咯。看起来舒服、注释到位的代码是衡量一段代码质量的标准之一,个人是这么认为哈。但是SA每天的工作不是一直在写代码,也许更多的是敲命令。  所以写脚本的时候,更为关注的应该是代码执行质量、运行效果而不是规范性。  当然,这不是说大批的linux SA写脚本没有规范性,不好看。24还是见过不少牛逼人物写的代码看起来很顺眼的,注释到位,提示合理,顺序清晰。刚好今天打酱油看到一篇shell脚本,写的非常好,是一个游戏脚本--“挖地雷”。像代码注释段,该有的信息都有,显得非常专业化,再者脚本的内容也看起来很舒服,可以说是化难为易。当然了,这里不是推荐大伙们去研究这段脚本,而是体会一下他的书写规范。不过能够把下面的内容理解了,自己在此基础上改进发布改进版,那是再好不过的事情啦。这段代码测试没问题的,24已经验证过了:  #!/bin/bash  #-------------CopyRight-------------  #   Name:Mine Sweeping  #   Version Number:1.00  #   Type:game  #   Language:bash shell  #   Date:2005-10-26  #   Author:BitBull  #   Email:BitBull.cn(at)gmail.com  #------------Environment------------  #   Terminal: column 80 line 24  #   Linux 2.6.9 i686  #   GNU Bash 3.00.15  #-----------------------------------  #---------------Define--------------  ECHO="echo -ne"  ESC="\033["  OK=0  FALSE=1  #--------------Variable--------------  #ANSI ESC action  FLASH=5  REV=7  #color  NULL=0  BLACK=30  RED=31  GREEN=32  ORANGE=33  BLUE=34  PURPLE=35  SBLUE=36  GREY=37  #back color  BBLACK=40  BRED=41  BGREEN=42  BORANGE=43  BBLUE=44  BPURPLE=45  BSBLUE=46  BGREY=47  MINE='@'  FLAG='F'  NUL=' '  SHADOW='X'  X=0  Y=0  CurX=1 #cur's X  CurY=1 #cur's Y  OCurX=1 #old cur's X  OCurY=1 #old cur's Y  MCount=0 #count mine  FCount=0 #count flag  SCount=0 #count shadow  MXYp=0 #MXY Array's ptr  #---------------Array----------------  #if ${XY[]} == M { mine }  #if ${XY[]} == F { flag }  #if ${XY[]} == N { null }  #if ${XY[]} == S { shadow }  #if ${XY[]} == [1-8] { tip_num }  #${XY[]} init in XYInit(i)  MXY[0]=""  #--------------Function--------------  function SttyInit ()  {  stty_save=$(stty -g) #backup stty  clear  trap "GameExit;" 2 15  stty -echo  $ECHO "${ESC}?25l" #hidden cursor  return $OK  }  function GameExit ()  {  stty $stty_save  stty echo  clear  trap 2 15  $ECHO "${ESC}?25h${ESC}0;0H${ESC}0m"  exit $OK  }  #print help  function Help ()  {  msg="Move:w s a d Dig:j Flag:f NewGame:n Exit:x   --CopyRight-- -2005-10-28 BitBull--"  $ECHO "${ESC}${REV};${RED}m${ESC}24;1H${msg}${ESC}${NULL}m"  return $OK  }  #print dialog window in screen  function PMsg ()  {  local title="$1" content="$2" greeting="$3"  $ECHO "${ESC}${RED}m"  $ECHO "${ESC}11;20H ------------------------------------------- "  $ECHO "${ESC}12;20H|         ======>$title<======           |"  $ECHO "${ESC}13;20H|         $content          |"  $ECHO "${ESC}14;20H|         ======>$greeting<======           |"  $ECHO "${ESC}15;20H ------------------------------------------- "  $ECHO "${ESC}${NULL}m"  return $OK  }  #print menu and player choose level,then ${X,Y,MCount,FCount,SCount} init  function Menu ()  {  local key  $ECHO "${ESC}6;1H${ESC}${RED}m"  cat《MENUEND  +++++++++++++++++++++++++++++  +        (1) Easy           +  +        (2) Normal         +  +        (3) Hardly         +  +        (4) Exit           +  +++++++++++++++++++++++++++++  MENUEND  $ECHO "${ESC}${NULL}m"  while read -s -n 1 key  do  case $key in  1) X=10;Y=10;MCount=10;FCount=10;SCount=100;break  ;;  2) X=20;Y=14;MCount=28;FCount=28;SCount=280;break  ;;  3) X=36;Y=18;MCount=65;FCount=65;SCount=648;break  ;;  4) GameExit  ;;  esac  done  return $OK  }  #receive CurX CurY,put it into XY[CurX+X*(CurY-1))]  #if $# == 3;write into XY[]  #if $# == 2;read from XY[]  function XYFormat ()  {  local XTmp=$1 YTmp=$2  if [[ $# -eq 3 ]]  then XY[$XTmp+$X*($YTmp-1)]=$3  else echo ${XY[$XTmp+$X*($YTmp-1)]}  fi  return $OK  }  function DrawInit ()  {  local DIline DIline2  DIline=$( for (( i=1; i<$((X*2)); i++ )) do $ECHO '-';done )  DIline2=$( for (( i=0; i<X; i++ )) do $ECHO "|${ESC}${SBLUE}mX${ESC}${NULL}m";done )  clear  Help  $ECHO "${ESC}1;1H+${DIline}+"  for (( i=0; i<Y; i++ ))  do  $ECHO "${ESC}$((i+2));1H${DIline2}|"  done  $ECHO "${ESC}$((Y+2));1H+${DIline}+"  return $OK  }  #${XY[*]}=S  function XYInit ()  {  for (( i=1; i<=$X; i++ ))  do  for (( j=1; j<=$Y; j++ ))  do  XYFormat $i $j S  done  done  return $OK  }  #check X Y  function CheckXY ()  {  local XYTmp="$1 $2"  for(( i=0; i<MXYp; i++ ))  do  if [[ "${MXY[i]}" == "$XYTmp" ]]  then return $FALSE  fi  done  return $OK  }  #RANDOM mine's X Y  function XYRand ()  {  local XTmp YTmp  for(( i=0; i<MCount; i++ ))  do  while :  do  XTmp=$(( RANDOM % ( X - 1 ) + 1 ))  YTmp=$(( RANDOM % ( Y - 1 ) + 1 ))  CheckXY $XTmp $YTmp  if [[ "$?" == "$OK" ]]  then  XYFormat $XTmp $YTmp M  MXY[i]="$XTmp $YTmp"  (( ++MXYp ))  break  else continue  fi  done  done  return $OK  }  #DEBUG  # print ${XY[*]} into ./mine.tmp  #you can read mine.tmp to know where is mine,xixi~~:)  #M is mine  function DEBUGPXY ()  {  rm mine.tmp>/dev/null 2>&1  for(( i=1; i<=$Y; i++ ))  do  for(( j=1; j<=$X; j++))  do  $ECHO "$(XYFormat $j $i)"》mine.tmp  done  $ECHO " "》mine.tmp  done  return $OK  }  #move cur  #usage:CurMov [UP|DOWN|LEFT|RIGHT]  function CurMov ()  {  local direction=$1 Xmin=1 Ymin=1 Xmax=$X Ymax=$Y  OCurX=$CurX  OCurY=$CurY  case $direction        in  "UP")        if [[ $CurY -gt $Ymin ]];then (( CurY-- ));fi  ;;  "DOWN")        if [[ $CurY -lt $Ymax ]];then (( CurY++ ));fi  ;;  "LEFT") if [[ $CurX -gt $Xmin ]];then (( CurX-- ));fi  ;;  "RIGHT")if [[ $CurX -lt $Xmax ]];then (( CurX++ ));fi  ;;  esac  if [[ $CurX != $OCurX || $CurY != $OCurY ]]  then DrawPoint $CurX $CurY CUR  fi  return $OK  }  #display point  #include cur,flag,mine,shadow,nul,tip [1-8]  function DrawPoint ()  {  local TCurX=$(( $1 * 2 )) TCurY=$(( $2 + 1 )) Type=$3  local TOCurX=$(( OCurX * 2 )) TOCurY=$(( OCurY + 1 ))  local colr=0 osign=0 sign=0  case $Type in  "CUR")  case $(XYFormat $OCurX $OCurY) in  F)        colr=$PURPLE;osign=$FLAG;;  N)        colr=$NULL;osign=$NUL;;  [1-8])        colr=$ORANGE;osign=$(XYFormat $OCurX $OCurY);;  [SM])        colr=$SBLUE;osign=$SHADOW;;  esac  case $(XYFormat $CurX $CurY) in  F)      sign=$FLAG;;  N)      sign=$NUL;;  [1-8])        sign=$(XYFormat $CurX $CurY);;  [SM])     sign=$SHADOW;;  esac  $ECHO "${ESC}${colr}m${ESC}${TOCurY};${TOCurX}H${osign}${ESC}${NULL}m"  $ECHO "${ESC}${REV};${FLASH};${ORANGE}m${ESC}${TCurY};${TCurX}H${sign}${ESC}${NULL}m"  ;;  "SHADOW")  $ECHO "${ESC}${SBLUE}m${ESC}${TCurY};${TCurX}H${SHADOW}${ESC}${NULL}m"  ;;  "MINE")  $ECHO "${ESC}${REV};${RED}m${ESC}${TCurY};${TCurX}H${MINE}${ESC}${NULL}m"  ;;  "FLAG")  $ECHO "${ESC}${TCurY};${TCurX}H${ESC}${PURPLE}m${FLAG}${ESC}${NULL}m"  ;;  [1-8])  $ECHO "${ESC}${TCurY};${TCurX}H${ESC}${ORANGE}m${Type}${ESC}${NULL}m"  ;;  "NUL")  $ECHO "${ESC}${TCurY};${TCurX}H${NUL}"  esac  return $OK  }  #check xy  function Loop ()  {  local XYTmp="$1 $2"  for (( i=0; i<MXYp; i++ ))  do  if [[ "$XYTmp" == "${MXY[i]}" ]]  then $ECHO 1  fi  done  return $OK  }  #count around mine  #A B C  #D X E  #F G H  #return mine's number  function CountM ()  {  local Xmin=1 Ymin=1 Xmax=$X Ymax=$Y minecount=0 n=0  #A  if [[ ( $CurX -gt $Xmin ) && ( $CurY -gt $Ymin ) ]]  then  n=$( Loop $((CurX-1)) $((CurY-1)) )  (( minecount += n ))  n=0  fi  #B  if [[ $CurY -gt $Ymin ]]  then  n=$( Loop $CurX $((CurY-1)) )  (( minecount += n ))  n=0  fi  #C  if [[ ( $CurX -lt $Xmax ) && ( $CurY -gt $Ymin ) ]]  then  n=$( Loop $((CurX+1)) $((CurY-1)) )  (( minecount += n ))  n=0  fi  #D  if [[ $CurX -gt $Xmin ]]  then  n=$( Loop $((CurX-1)) $CurY )  (( minecount += n ))  n=0  fi  #E  if [[ $CurX -lt $Xmax ]]  then  n=$( Loop $((CurX+1)) $CurY )  (( minecount += n ))  n=0  fi  #F  if [[ ( $CurX -gt $Xmin ) && ( $CurY -lt $Ymax ) ]]  then  n=$( Loop $((CurX-1)) $((CurY+1)) )  (( minecount += n ))  n=0  fi  #G  if [[ $CurY -lt $Ymax ]]  then  n=$( Loop $CurX $((CurY+1)) )  (( minecount += n ))  n=0  fi  #H  if [[ ( $CurX -lt $Xmax ) && ( $CurY -lt $Ymax ) ]]  then  n=$( Loop $((CurX+1)) $((CurY+1)) )  (( minecount += n ))  n=0  fi  return $minecount  }  #dig  #if mine ,gameover  #else tip around mine's number  function Dig ()  {  local key minenum=0  case $(XYFormat $CurX $CurY) in  M)  DrawPoint $CurX $CurY MINE  read -s -n 1 key  GameOver "Game Over"  ;;  S)  CountM  minenum=$?  if [[ $minenum -eq $NULL ]]  then  XYFormat $CurX $CurY N  DrawPoint $CurX $CurY NUL  else  XYFormat $CurX $CurY $minenum  DrawPoint $CurX $CurY $minenum  fi  (( SCount-- ))  if [[ $SCount -eq $MCount ]]  then GameOver "Well Done"  fi  ;;  esac  DrawPoint $CurX $CurY CUR  return $OK  }  #draw flag's number  function DrawFCount ()  {  $ECHO "${ESC}22;34H${ESC};${PURPLE}mFLAG=${FCount}  ${ESC}${NULL}m"  }  #sign mine  function Flag ()  {  local XYTmp="$CurX $CurY";stat=$FALSE  case $(XYFormat $CurX $CurY) in  F)  for (( i=1; i<MXYp; i++ ))  do  if [[ "${MXY[i]}" == "$XYTmp" ]]  then XYFormat $CurX $CurY M;stat=$OK;break  fi  done  if [[ $stat == $FALSE ]]  then XYFormat $CurX $CurY S  fi  DrawPoint $CurX $CurY SHADOW  (( FCount++ ))  DrawFCount  ;;  [SM])  if [[ $FCount -eq $NULL ]]  then return $FALSE  fi  DrawPoint $CurX $CurY FLAG  XYFormat $CurX $CurY F  (( FCount-- ))  DrawFCount  ;;  esac  DrawPoint $CurX $CurY CUR  return $OK  }  function GameOver ()  {  local key msgtitle=$1  PMsg "$msgtitle" "Do you want replay?<y/n>" "Thank You"  while read -s -n 1 key  do  case $key in  [yY])        exec $(dirname $0)/$(basename $0);;  [nN])        GameExit;;  *)        continue;;  esac  done  return $OK  }  #main  #drawscreen and control  function Main ()  {  local key  XYInit  XYRand  ############################  # if you enable DEBUGPXY,  #you can know where is mine  #        DEBUGPXY  #delete this line's #  #then cat ./mine.tmp  ############################  DrawPoint $CurX $CurY CUR  DrawFCount  while read -s -n 1 key  do  case $key in  [wW])        CurMov UP;;  [sS])        CurMov DOWN;;  [aA])        CurMov LEFT;;  [dD])        CurMov RIGHT;;  [jJ])        Dig;;  [fF])        Flag;;  [nN])        exec $(dirname $0)/$(basename $0);;  [xX])        GameExit;;  esac  done  return $OK  }  #---------------Main-----------------  SttyInit  Menu #X Y MCount FCount SCount OK!  DrawInit  Main
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部