修改SEO Smart Links兼容syntaxhighlighter

为了防止代码出错,之前一直是用coolcode来展示代码,这个是不支持bash高亮。之前也找过几次,也没找到支持bash的,就算支持,也不好用。coolcode虽然一直在用来展未代码防止出错,但没有高亮bash一直挺不爽,今天试用了SyntaxHighlighter Evolved,还不错,但不知道为什么无法开启工具条,就这样用着吧。安装好测试发现SEO Smart Links把高亮里的代码添加了链接,于是有了此文,下面是修改SEO Smart Links来兼容syntaxhighlighter的方法。
1、找到

  1. add_filter(‘the_content’,  array(&$this, ‘SEOLinks_the_content_filter’), 10);

把10修改为5,有两处。
2、找到

  1. $text = preg_replace(‘%(<h.*?>)(.*?)(</h.*?>)%sie’, "’\1′.insertspecialchars(‘\2’).’\3’", $text);

在此条代码下面添加:

  1. $text = preg_replace(‘%(【bash】)(.*?)(【/bash】)%sie’, "’\1′.insertspecialchars(‘\2’).’\3’", $text);

3、找到

  1. $text = preg_replace(‘%(<h.*?>)(.*?)(</h.*?>)%sie’, "’\1′.removespecialchars(‘\2’).’\3’", $text);

在下面添加:

  1. $text = preg_replace(‘%(【bash】)(.*?)(【/bash】)%sie’, "’\1′.removespecialchars(‘\2’).’\3’", $text);

注意:
1、我这里用使用【bash】和【/bash】来标识代码,如果你是使用其它标识,你修改2、3步骤代码。
2、请将【】更改为[],这里使用【】是保证能正常显示出来。

shell脚本制作俄罗斯方块游戏

下面的脚本功能强大,make by xhchen,收藏一下。

 

  1. #!/bin/bash
  2.  
  3. # Tetris Game
  4. # 10.21.2003 xhchen<[email][email protected][/email]>
  5.  
  6. #APP declaration
  7. APP_NAME="${0##*[\/]}"
  8. APP_VERSION="1.0"
  9.  
  10.  
  11. #颜色定义
  12. cRed=1
  13. cGreen=2
  14. cYellow=3
  15. cBlue=4
  16. cFuchsia=5
  17. cCyan=6
  18. cWhite=7
  19. colorTable=($cRed $cGreen $cYellow $cBlue $cFuchsia $cCyan $cWhite)
  20.  
  21. #位置和大小
  22. iLeft=3
  23. iTop=2
  24. ((iTrayLeft = iLeft + 2))
  25. ((iTrayTop = iTop + 1))
  26. ((iTrayWidth = 10))
  27. ((iTrayHeight = 15))
  28.  
  29. #颜色设置
  30. cBorder=$cGreen
  31. cScore=$cFuchsia
  32. cScoreValue=$cCyan
  33.  
  34. #控制信号
  35. #改游戏使用两个进程,一个用于接收输入,一个用于游戏流程和显示界面;
  36. #当前者接收到上下左右等按键时,通过向后者发送signal的方式通知后者。
  37. sigRotate=25
  38. sigLeft=26
  39. sigRight=27
  40. sigDown=28
  41. sigAllDown=29
  42. sigExit=30
  43.  
  44. #七中不同的方块的定义
  45. #通过旋转,每种方块的显示的样式可能有几种
  46. box0=(0 0 0 1 1 0 1 1)
  47. box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)
  48. box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)
  49. box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)
  50. 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)
  51. 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)
  52. 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)
  53. #所有其中方块的定义都放到box变量中
  54. box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})
  55. #各种方块旋转后可能的样式数目
  56. countBox=(1 2 2 2 4 4 4)
  57. #各种方块再box数组中的偏移
  58. offsetBox=(0 1 3 5 7 11 15)
  59.  
  60. #每提高一个速度级需要积累的分数
  61. iScoreEachLevel=50        #be greater than 7
  62.  
  63. #运行时数据
  64. sig=0                #接收到的signal
  65. iScore=0        #总分
  66. iLevel=0        #速度级
  67. boxNew=()        #新下落的方块的位置定义
  68. cBoxNew=0        #新下落的方块的颜色
  69. iBoxNewType=0        #新下落的方块的种类
  70. iBoxNewRotate=0        #新下落的方块的旋转角度
  71. boxCur=()        #当前方块的位置定义
  72. cBoxCur=0        #当前方块的颜色
  73. iBoxCurType=0        #当前方块的种类
  74. iBoxCurRotate=0        #当前方块的旋转角度
  75. boxCurX=-1        #当前方块的x坐标位置
  76. boxCurY=-1        #当前方块的y坐标位置
  77. iMap=()                #背景方块图表
  78.  
  79. #初始化所有背景方块为-1, 表示没有方块
  80. for ((i = 0; i < iTrayHeight * iTrayWidth; i++)); do iMap[$i]=-1; done
  81.  
  82.  
  83. #接收输入的进程的主函数
  84. function RunAsKeyReceiver()
  85. {
  86.         local pidDisplayer key aKey sig cESC sTTY
  87.  
  88.         pidDisplayer=$1
  89.         aKey=(0 0 0)
  90.  
  91.         cESC=`echo -ne "33"`
  92.         cSpace=`echo -ne "40"`
  93.  
  94.         #保存终端属性。在read -s读取终端键时,终端的属性会被暂时改变。
  95.         #如果在read -s时程序被不幸杀掉,可能会导致终端混乱,
  96.         #需要在程序退出时恢复终端属性。
  97.         sTTY=`stty -g`
  98.  
  99.         #捕捉退出信号
  100.         trap "MyExit;" INT TERM
  101.         trap "MyExitNoSub;" $sigExit
  102.  
  103.         #隐藏光标
  104.         echo -ne "33[?25l"
  105.  
  106.  
  107.         while :
  108.         do
  109.                 #读取输入。注-s不回显,-n读到一个字符立即返回
  110.                 read -s -n 1 key
  111.  
  112.                 aKey[0]=${aKey[1]}
  113.                 aKey[1]=${aKey[2]}
  114.                 aKey[2]=$key
  115.                 sig=0
  116.  
  117.                 #判断输入了何种键
  118.                 if [[ $key == $cESC && ${aKey[1]} == $cESC ]]
  119.                 then
  120.                         #ESC键
  121.                         MyExit
  122.                 elif [[ ${aKey[0]} == $cESC && ${aKey[1]} == "[" ]]
  123.                 then
  124.                         if [[ $key == "A" ]]; then sig=$sigRotate        #<向上键>
  125.                         elif [[ $key == "B" ]]; then sig=$sigDown        #<向下键>
  126.                         elif [[ $key == "D" ]]; then sig=$sigLeft        #<向左键>
  127.                         elif [[ $key == "C" ]]; then sig=$sigRight        #<向右键>
  128.                         fi
  129.                 elif [[ $key == "W" || $key == "w" ]]; then sig=$sigRotate        #W, w
  130.                 elif [[ $key == "S" || $key == "s" ]]; then sig=$sigDown        #S, s
  131.                 elif [[ $key == "A" || $key == "a" ]]; then sig=$sigLeft        #A, a
  132.                 elif [[ $key == "D" || $key == "d" ]]; then sig=$sigRight        #D, d
  133.                 elif [[ "[$key]" == "[]" ]]; then sig=$sigAllDown        #空格键
  134.                 elif [[ $key == "Q" || $key == "q" ]]                        #Q, q
  135.                 then
  136.                         MyExit
  137.                 fi
  138.  
  139.                 if [[ $sig != 0 ]]
  140.                 then
  141.                         #向另一进程发送消息
  142.                         kill -$sig $pidDisplayer
  143.                 fi
  144.         done
  145. }
  146.  
  147. #退出前的恢复
  148. function MyExitNoSub()
  149. {
  150.         local y
  151.  
  152.         #恢复终端属性
  153.         stty $sTTY
  154.         ((y = iTop + iTrayHeight + 4))
  155.  
  156.         #显示光标
  157.         echo -e "33[?25h33[${y};0H"
  158.         exit
  159. }
  160.  
  161.  
  162. function MyExit()
  163. {
  164.         #通知显示进程需要退出
  165.         kill -$sigExit $pidDisplayer
  166.  
  167.         MyExitNoSub
  168. }
  169.  
  170.  
  171. #处理显示和游戏流程的主函数
  172. function RunAsDisplayer()
  173. {
  174.         local sigThis
  175.         InitDraw
  176.  
  177.         #挂载各种信号的处理函数
  178.         trap "sig=$sigRotate;" $sigRotate
  179.         trap "sig=$sigLeft;" $sigLeft
  180.         trap "sig=$sigRight;" $sigRight
  181.         trap "sig=$sigDown;" $sigDown
  182.         trap "sig=$sigAllDown;" $sigAllDown
  183.         trap "ShowExit;" $sigExit
  184.  
  185.         while :
  186.         do
  187.                 #根据当前的速度级iLevel不同,设定相应的循环的次数
  188.                 for ((i = 0; i < 21 – iLevel; i++))
  189.                 do
  190.                         sleep 0.02
  191.                         sigThis=$sig
  192.                         sig=0
  193.  
  194.                         #根据sig变量判断是否接受到相应的信号
  195.                         if ((sigThis == sigRotate)); then BoxRotate;        #旋转
  196.                         elif ((sigThis == sigLeft)); then BoxLeft;        #左移一列
  197.                         elif ((sigThis == sigRight)); then BoxRight;        #右移一列
  198.                         elif ((sigThis == sigDown)); then BoxDown;        #下落一行
  199.                         elif ((sigThis == sigAllDown)); then BoxAllDown;        #下落到底
  200.                         fi
  201.                 done
  202.                 #kill -$sigDown $$
  203.                 BoxDown        #下落一行
  204.         done
  205. }
  206.  
  207.  
  208. #BoxMove(y, x), 测试是否可以把移动中的方块移到(x, y)的位置, 返回0则可以, 1不可以
  209. function BoxMove()
  210. {
  211.         local j i x y xTest yTest
  212.         yTest=$1
  213.         xTest=$2
  214.         for ((j = 0; j < 8; j += 2))
  215.         do
  216.                 ((i = j + 1))
  217.                 ((y = ${boxCur[$j]} + yTest))
  218.                 ((x = ${boxCur[$i]} + xTest))
  219.                 if (( y < 0 || y >= iTrayHeight || x < 0 || x >= iTrayWidth))
  220.                 then
  221.                         #撞到墙壁了
  222.                         return 1
  223.                 fi
  224.                 if ((${iMap[y * iTrayWidth + x]} != -1 ))
  225.                 then
  226.                         #撞到其他已经存在的方块了
  227.                         return 1
  228.                 fi
  229.         done
  230.         return 0;
  231. }
  232.  
  233.  
  234. #将当前移动中的方块放到背景方块中去,
  235. #并计算新的分数和速度级。(即一次方块落到底部)
  236. function Box2Map()
  237. {
  238.         local j i x y xp yp line
  239.  
  240.         #将当前移动中的方块放到背景方块中去
  241.         for ((j = 0; j < 8; j += 2))
  242.         do
  243.                 ((i = j + 1))
  244.                 ((y = ${boxCur[$j]} + boxCurY))
  245.                 ((x = ${boxCur[$i]} + boxCurX))
  246.                 ((i = y * iTrayWidth + x))
  247.                 iMap[$i]=$cBoxCur
  248.         done
  249.  
  250.         #消去可被消去的行
  251.         line=0
  252.         for ((j = 0; j < iTrayWidth * iTrayHeight; j += iTrayWidth))
  253.         do
  254.                 for ((i = j + iTrayWidth – 1; i >= j; i–))
  255.                 do
  256.                         if ((${iMap[$i]} == -1)); then break; fi
  257.                 done
  258.                 if ((i >= j)); then continue; fi
  259.  
  260.                 ((line++))
  261.                 for ((i = j – 1; i >= 0; i–))
  262.                 do
  263.                         ((x = i + iTrayWidth))
  264.                         iMap[$x]=${iMap[$i]}
  265.                 done
  266.                 for ((i = 0; i < iTrayWidth; i++))
  267.                 do
  268.                         iMap[$i]=-1
  269.                 done
  270.         done
  271.  
  272.         if ((line == 0)); then return; fi
  273.  
  274.         #根据消去的行数line计算分数和速度级
  275.         ((x = iLeft + iTrayWidth * 2 + 7))
  276.         ((y = iTop + 11))
  277.         ((iScore += line * 2 – 1))
  278.         #显示新的分数
  279.         echo -ne "33[1m33[3${cScoreValue}m33[${y};${x}H${iScore}         "
  280.         if ((iScore % iScoreEachLevel < line * 2 – 1))
  281.         then
  282.                 if ((iLevel < 20))
  283.                 then
  284.                         ((iLevel++))
  285.                         ((y = iTop + 14))
  286.                         #显示新的速度级
  287.                         echo -ne "33[3${cScoreValue}m33[${y};${x}H${iLevel}        "
  288.                 fi
  289.         fi
  290.         echo -ne "33[0m"
  291.  
  292.  
  293.         #重新显示背景方块
  294.         for ((y = 0; y < iTrayHeight; y++))
  295.         do
  296.                 ((yp = y + iTrayTop + 1))
  297.                 ((xp = iTrayLeft + 1))
  298.                 ((i = y * iTrayWidth))
  299.                 echo -ne "33[${yp};${xp}H"
  300.                 for ((x = 0; x < iTrayWidth; x++))
  301.                 do
  302.                         ((j = i + x))
  303.                         if ((${iMap[$j]} == -1))
  304.                         then
  305.                                 echo -ne "  "
  306.                         else
  307.                                 echo -ne "33[1m33[7m33[3${iMap[$j]}m33[4${iMap[$j]}m[]33[0m"
  308.                         fi
  309.                 done
  310.         done
  311. }
  312.  
  313.  
  314. #下落一行
  315. function BoxDown()
  316. {
  317.         local y s
  318.         ((y = boxCurY + 1))        #新的y坐标
  319.         if BoxMove $y $boxCurX        #测试是否可以下落一行
  320.         then
  321.                 s="`DrawCurBox 0`"        #将旧的方块抹去
  322.                 ((boxCurY = y))
  323.                 s="$s`DrawCurBox 1`"        #显示新的下落后方块
  324.                 echo -ne $s
  325.         else
  326.                 #走到这儿, 如果不能下落了
  327.                 Box2Map                #将当前移动中的方块贴到背景方块中
  328.                 RandomBox        #产生新的方块
  329.         fi
  330. }
  331.  
  332. #左移一列
  333. function BoxLeft()
  334. {
  335.         local x s
  336.         ((x = boxCurX – 1))
  337.         if BoxMove $boxCurY $x
  338.         then
  339.                 s=`DrawCurBox 0`
  340.                 ((boxCurX = x))
  341.                 s=$s`DrawCurBox 1`
  342.                 echo -ne $s
  343.         fi
  344. }
  345.  
  346. #右移一列
  347. function BoxRight()
  348. {
  349.         local x s
  350.         ((x = boxCurX + 1))
  351.         if BoxMove $boxCurY $x
  352.         then
  353.                 s=`DrawCurBox 0`
  354.                 ((boxCurX = x))
  355.                 s=$s`DrawCurBox 1`
  356.                 echo -ne $s
  357.         fi
  358. }
  359.  
  360.  
  361. #下落到底
  362. function BoxAllDown()
  363. {
  364.         local k j i x y iDown s
  365.         iDown=$iTrayHeight
  366.  
  367.         #计算一共需要下落多少行
  368.         for ((j = 0; j < 8; j += 2))
  369.         do
  370.                 ((i = j + 1))
  371.                 ((y = ${boxCur[$j]} + boxCurY))
  372.                 ((x = ${boxCur[$i]} + boxCurX))
  373.                 for ((k = y + 1; k < iTrayHeight; k++))
  374.                 do
  375.                         ((i = k * iTrayWidth + x))
  376.                         if (( ${iMap[$i]} != -1)); then break; fi
  377.                 done
  378.                 ((k -= y + 1))
  379.                 if (( $iDown > $k )); then iDown=$k; fi
  380.         done
  381.  
  382.         s=`DrawCurBox 0`        #将旧的方块抹去
  383.         ((boxCurY += iDown))
  384.         s=$s`DrawCurBox 1`        #显示新的下落后的方块
  385.         echo -ne $s
  386.         Box2Map                #将当前移动中的方块贴到背景方块中
  387.         RandomBox        #产生新的方块
  388. }
  389.  
  390.  
  391. #旋转方块
  392. function BoxRotate()
  393. {
  394.         local iCount iTestRotate boxTest j i s
  395.         iCount=${countBox[$iBoxCurType]}        #当前的方块经旋转可以产生的样式的数目
  396.  
  397.         #计算旋转后的新的样式
  398.         ((iTestRotate = iBoxCurRotate + 1))
  399.         if ((iTestRotate >= iCount))
  400.         then
  401.                 ((iTestRotate = 0))
  402.         fi
  403.  
  404.         #更新到新的样式, 保存老的样式(但不显示)
  405.         for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++))
  406.         do
  407.                 boxTest[$j]=${boxCur[$j]}
  408.                 boxCur[$j]=${box[$i]}
  409.         done
  410.  
  411.         if BoxMove $boxCurY $boxCurX        #测试旋转后是否有空间放的下
  412.         then
  413.                 #抹去旧的方块
  414.                 for ((j = 0; j < 8; j++))
  415.                 do
  416.                         boxCur[$j]=${boxTest[$j]}
  417.                 done
  418.                 s=`DrawCurBox 0`
  419.  
  420.                 #画上新的方块
  421.                 for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++))
  422.                 do
  423.                         boxCur[$j]=${box[$i]}
  424.                 done
  425.                 s=$s`DrawCurBox 1`
  426.                 echo -ne $s
  427.                 iBoxCurRotate=$iTestRotate
  428.         else
  429.                 #不能旋转,还是继续使用老的样式
  430.                 for ((j = 0; j < 8; j++))
  431.                 do
  432.                         boxCur[$j]=${boxTest[$j]}
  433.                 done
  434.         fi
  435. }
  436.  
  437.  
  438. #DrawCurBox(bDraw), 绘制当前移动中的方块, bDraw为1, 画上, bDraw为0, 抹去方块。
  439. function DrawCurBox()
  440. {
  441.         local i j t bDraw sBox s
  442.         bDraw=$1
  443.  
  444.         s=""
  445.         if (( bDraw == 0 ))
  446.         then
  447.                 sBox="4040"
  448.         else
  449.                 sBox="[]"
  450.                 s=$s"33[1m33[7m33[3${cBoxCur}m33[4${cBoxCur}m"
  451.         fi
  452.  
  453.         for ((j = 0; j < 8; j += 2))
  454.         do
  455.                 ((i = iTrayTop + 1 + ${boxCur[$j]} + boxCurY))
  456.                 ((t = iTrayLeft + 1 + 2 * (boxCurX + ${boxCur[$j + 1]})))
  457.                 #33[y;xH, 光标到(x, y)处
  458.                 s=$s"33[${i};${t}H${sBox}"
  459.         done
  460.         s=$s"33[0m"
  461.         echo -n $s
  462. }
  463.  
  464.  
  465. #更新新的方块
  466. function RandomBox()
  467. {
  468.         local i j t
  469.  
  470.         #更新当前移动的方块
  471.         iBoxCurType=${iBoxNewType}
  472.         iBoxCurRotate=${iBoxNewRotate}
  473.         cBoxCur=${cBoxNew}
  474.         for ((j = 0; j < ${#boxNew[@]}; j++))
  475.         do
  476.                 boxCur[$j]=${boxNew[$j]}
  477.         done
  478.  
  479.  
  480.         #显示当前移动的方块
  481.         if (( ${#boxCur[@]} == 8 ))
  482.         then
  483.                 #计算当前方块该从顶端哪一行"冒"出来
  484.                 for ((j = 0, t = 4; j < 8; j += 2))
  485.                 do
  486.                         if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi
  487.                 done
  488.                 ((boxCurY = -t))
  489.                 for ((j = 1, i = -4, t = 20; j < 8; j += 2))
  490.                 do
  491.                         if ((${boxCur[$j]} > i)); then i=${boxCur[$j]}; fi
  492.                         if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi
  493.                 done
  494.                 ((boxCurX = (iTrayWidth – 1 – i – t) / 2))
  495.  
  496.                 #显示当前移动的方块
  497.                 echo -ne `DrawCurBox 1`
  498.  
  499.                 #如果方块一出来就没处放,Game over!
  500.                 if ! BoxMove $boxCurY $boxCurX
  501.                 then
  502.                         kill -$sigExit ${PPID}
  503.                         ShowExit
  504.                 fi
  505.         fi
  506.  
  507.  
  508.  
  509.         #清除右边预显示的方块
  510.         for ((j = 0; j < 4; j++))
  511.         do
  512.                 ((i = iTop + 1 + j))
  513.                 ((t = iLeft + 2 * iTrayWidth + 7))
  514.                 echo -ne "33[${i};${t}H        "
  515.         done
  516.  
  517.         #随机产生新的方块
  518.         ((iBoxNewType = RANDOM % ${#offsetBox[@]}))
  519.         ((iBoxNewRotate = RANDOM % ${countBox[$iBoxNewType]}))
  520.         for ((j = 0, i = (${offsetBox[$iBoxNewType]} + $iBoxNewRotate) * 8; j < 8; j++, i++))
  521.         do
  522.                 boxNew[$j]=${box[$i]};
  523.         done
  524.  
  525.         ((cBoxNew = ${colorTable[RANDOM % ${#colorTable[@]}]}))
  526.  
  527.         #显示右边预显示的方块
  528.         echo -ne "33[1m33[7m33[3${cBoxNew}m33[4${cBoxNew}m"
  529.         for ((j = 0; j < 8; j += 2))
  530.         do
  531.                 ((i = iTop + 1 + ${boxNew[$j]}))
  532.                 ((t = iLeft + 2 * iTrayWidth + 7 + 2 * ${boxNew[$j + 1]}))
  533.                 echo -ne "33[${i};${t}H[]"
  534.         done
  535.         echo -ne "33[0m"
  536. }
  537.  
  538.  
  539. #初始绘制
  540. function InitDraw()
  541. {
  542.         clear
  543.         RandomBox        #随机产生方块,这时右边预显示窗口中有方快了
  544.         RandomBox        #再随机产生方块,右边预显示窗口中的方块被更新,原先的方块将开始下落
  545.         local i t1 t2 t3
  546.  
  547.         #显示边框
  548.         echo -ne "33[1m"
  549.         echo -ne "33[3${cBorder}m33[4${cBorder}m"
  550.  
  551.         ((t2 = iLeft + 1))
  552.         ((t3 = iLeft + iTrayWidth * 2 + 3))
  553.         for ((i = 0; i < iTrayHeight; i++))
  554.         do
  555.                 ((t1 = i + iTop + 2))
  556.                 echo -ne "33[${t1};${t2}H||"
  557.                 echo -ne "33[${t1};${t3}H||"
  558.         done
  559.  
  560.         ((t2 = iTop + iTrayHeight + 2))
  561.         for ((i = 0; i < iTrayWidth + 2; i++))
  562.         do
  563.                 ((t1 = i * 2 + iLeft + 1))
  564.                 echo -ne "33[${iTrayTop};${t1}H=="
  565.                 echo -ne "33[${t2};${t1}H=="
  566.         done
  567.         echo -ne "33[0m"
  568.  
  569.  
  570.         #显示"Score"和"Level"字样
  571.         echo -ne "33[1m"
  572.         ((t1 = iLeft + iTrayWidth * 2 + 7))
  573.         ((t2 = iTop + 10))
  574.         echo -ne "33[3${cScore}m33[${t2};${t1}HScore"
  575.         ((t2 = iTop + 11))
  576.         echo -ne "33[3${cScoreValue}m33[${t2};${t1}H${iScore}"
  577.         ((t2 = iTop + 13))
  578.         echo -ne "33[3${cScore}m33[${t2};${t1}HLevel"
  579.         ((t2 = iTop + 14))
  580.         echo -ne "33[3${cScoreValue}m33[${t2};${t1}H${iLevel}"
  581.         echo -ne "33[0m"
  582. }
  583.  
  584.  
  585. #退出时显示GameOVer!
  586. function ShowExit()
  587. {
  588.         local y
  589.         ((y = iTrayHeight + iTrayTop + 3))
  590.         echo -e "33[${y};0HGameOver!33[0m"
  591.         exit
  592. }
  593.  
  594.  
  595. #显示用法.
  596. function Usage
  597. {
  598.         cat << EOF
  599. Usage: $APP_NAME
  600. Start tetris game.
  601.  
  602.   -h, –help              display this help and exit
  603.       –version           output version information and exit
  604. EOF
  605. }
  606.  
  607.  
  608. #游戏主程序在这儿开始.
  609. if [[ "$1" == "-h" || "$1" == "–help" ]]; then
  610.         Usage
  611. elif [[ "$1" == "–version" ]]; then
  612.         echo "$APP_NAME $APP_VERSION"
  613. elif [[ "$1" == "–show" ]]; then
  614.         #当发现具有参数–show时,运行显示函数
  615.         RunAsDisplayer
  616. else
  617.         bash $0 –show&        #以参数–show将本程序再运行一遍
  618.         RunAsKeyReceiver $!        #以上一行产生的进程的进程号作为参数
  619. fi

 

如何在Linux终端里用Shell和C输出带颜色的文字

我们知道,使用ls命令列出文件列表时,不同的文件类型会用不同的颜色显示。那么如何实现这样带颜色的文本输出呢?答案并不复杂,不管是用shell还是C语言。

一、shell下的实现方法

先来讲在shell下,如何实现。用echo命令就可以实现,参看以下例子:

echo -e “\033[32mHello, world!”

当你在终端里敲下这条命令后,是不是发现系统用绿色输出了”Hello,world!”,不止如此,连之后的命令提示符都变成了绿色?不要着急,听我继续说。echo命令-e选项的作用是激活终端对反斜线转义符(即\)的解释。引号内\033用于引导非常规字符序列,在这里的作用就是引导设置输出属性,后边的[32m就是将前景色设置为绿色,字母m表示设置的属性类别,数字代表属性值。设置可以单独使用,例如:

echo -e “\033[0m”

这行命令的作用是恢复属性为默认值,也就是说0m设置项用于恢复默认值。现在你的终端是不是又一切正常了?

理解了这些,剩下的就简单了。用这种命令,除了设置文本前景色,还可以设置很多属性。下边列出其他的设置项:

————————————————————————–

\033[0m 关闭所有属性
\033[1m 设置高亮度
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m 至 \33[37m 设置前景色
\033[40m 至 \33[47m 设置背景色
\033[nA 光标上移n行
\033[nB 光标下移n行
\033[nC 光标右移n行
\033[nD 光标左移n行
\033[y;xH设置光标位置
\033[2J 清屏
\033[K 清除从光标到行尾的内容
\033[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\033[?25h 显示光标

————————————————————————–

各数字所代表的颜色如下:

字背景颜色范围:40—-49
40:黑
41:深红
42:绿
43:黄色
44:蓝色
45:紫色
46:深绿
47:白色

字颜色:30———–39
30:黑
31:红
32:绿
33:黄
34:蓝色
35:紫色
36:深绿
37:白色

另外,同类的多种设置项可以组合在一起,中间用分号(;)隔开。如下:

echo -e “\033[20;1H\033[1;4;32mHello,world\033[0m”

这行命令首先\033[20;1H将光标移动到终端第20行第1列,之后的\033[1;4;32m将文本属性设置为高亮、带下划线且颜色为绿色,然后输出Hello,world;最后\033[0m将终端属性恢复为默认值,这样就不会看到连命令完成后的命令提示符也变了样儿了。

通过以上各种命令的组合就可以实现对终端输出地复杂控制。

二、如何在C编程中实现?

理解了以上在Shell中的实现方法,关于在C中如何实现就很简单了。可以说只需要用printf函数代替上边的echo -e就OK了。参见下例:

int color = 32;

printf(“\033[20;1H\033[1;4;%dmHello, world.\033[0m”, color);

这个例子类似上边shell中最后那个例子,只是这里颜色值通过变量color来指定(当然,也可以直接指定)。

三、联想

看到这里你可能会想,是不是在其他编程语言里也可以用类似的方法实现对终端输出的控制呢?答案是肯定的!比如在python中,可以如下输出:

color=32

print “\033[20;1H\033[1;4;%dHello, world.\033[0m”%color

这个例子的效果跟上边C的例子是相同的。
转自:http://blog.csdn.net/acmee/article/details/6613060

shell采集系统cpu 内存 磁盘 网络信息

cpu信息采集


cpu使用率

采集算法
通过/proc/stat文件采集并计算CPU总使用率或者单个核使用率。以cpu0为例,算法如下:
1. cat /proc/stat | grep ‘cpu0’得到cpu0的信息
2. cpuTotal1=user+nice+system+idle+iowait+irq+softirq
3. cpuUsed1=user+nice+system+irq+softirq
4. sleep 30秒
5. 再次cat /proc/stat | grep ‘cpu0’ 得到cpu的信息
6. cpuTotal2=user+nice+system+idle+iowait+irq+softirq
7. cpuUsed2=user+nice+system+irq+softirq
8. 得到cpu0 在30秒内的单核利用率:(cpuUsed2 – cpuUsed1) * 100 / (cpuTotal2 – cpuTotal1)
相当于使用top –d 30命令,把user、nice、system、irq、softirq五项的使用率相加。
shell代码:

  1. a=(`cat /proc/stat | grep -E "cpub" | awk -v total=0 ‘{$1="";for(i=2;i<=NF;i++){total+=$i};used=$2+$3+$4+$7+$8 }END{print total,used}’`)
  2. sleep 30
  3. b=(`cat /proc/stat | grep -E "cpub" | awk -v total=0 ‘{$1="";for(i=2;i<=NF;i++){total+=$i};used=$2+$3+$4+$7+$8 }END{print total,used}’`)
  4. cpu_usage=(((${b[1]}-${a[1]})*100/(${b[0]}-${a[0]})))

cpu负载

采集算法:
读取/proc/loadavg得到机器的1/5/15分钟平均负载,再乘以100。
shell代码:

  1. cpuload=(`cat /proc/loadavg | awk ‘{print $1,$2,$3}’`)
  2. load1=${cpuload[0]}
  3. load5=${cpuload[1]}
  4. load15=${cpuload[2]}

内存采集


应用程序使用内存

采集算法:
读取/proc/meminfo文件,(MemTotal – MemFree – Buffers – Cached)/1024得到应用程序使用内存数。
shell代码:

  1. awk ‘/MemTotal/{total=$2}/MemFree/{free=$2}/Buffers/{buffers=$2}/^Cached/{cached=$2}END{print (total-free-buffers-cached)/1024}’  /proc/meminfo

MEM使用量

采集算法:
读取/proc/meminfo文件,MemTotal – MemFree得到MEM使用量。
shell代码:

  1. awk ‘/MemTotal/{total=$2}/MemFree/{free=$2}END{print (total-free)/1024}’  /proc/meminfo

SWAP使用大小

采集算法:
通过/proc/meminfo文件,SwapTotal – SwapFree得到SWAP使用大小。
shell代码:

  1. awk ‘/SwapTotal/{total=$2}/SwapFree/{free=$2}END{print (total-free)/1024}’  /proc/meminfo

磁盘信息采集


disk io

1、IN:平均每秒把数据从硬盘读到物理内存的数据量
采集算法:
读取/proc/vmstat文件得出最近240秒内pgpgin的增量,把pgpgin的增量再除以240得到每秒的平均增量。
相当于vmstat 240命令bi一列的输出。
shell代码:

  1. a=`awk ‘/pgpgin/{print $2}’ /proc/vmstat`
  2. sleep 240
  3. b=`awk ‘/pgpgin/{print $2}’ /proc/vmstat`
  4. ioin=$(((b-a)/240))

2、OUT:平均每秒把数据从物理内存写到硬盘的数据量
采集算法:
读取/proc/vmstat文件得出最近240秒内pgpgout的增量,把pgpgout的增量再除以240得到每秒的平均增量。
相当于vmstat 240命令bo一列的输出。
shell代码:

  1. a=`awk ‘/pgpgout/{print $2}’ /proc/vmstat`
  2. sleep 240
  3. b=`awk ‘/pgpgout/{print $2}’ /proc/vmstat`
  4. ioout=$(((b-a)/240))

网络


流量

以http://devops.webres.wang/为例,eth0是内网,eth1外网,获取60秒的流量。
机器网卡的平均每秒流量
采集算法:
读取/proc/net/dev文件,得到60秒内发送和接收的字节数(KB),然后乘以8,再除以60,得到每秒的平均流量。
shell代码:

  1. traffic_be=(`awk -F'[: ]+’ ‘BEGIN{ORS=" "}/eth0/{print $3,$10}/eth1/{print $3,$11}’ /proc/net/dev`)
  2. sleep 60
  3. traffic_af=(`awk -F'[: ]+’ ‘BEGIN{ORS=" "}/eth0/{print $3,$10}/eth1/{print $3,$11}’ /proc/net/dev`)
  4. eth0_in=$(( (${traffic_af[0]}-${traffic_be[0]})/60 ))
  5. eth0_out=$(( (${traffic_af[1]}-${traffic_be[1]})/60 ))
  6. eth1_in=$(( (${traffic_af[2]}-${traffic_be[2]})/60 ))
  7. eth1_out=$(( (${traffic_af[3]}-${traffic_be[3]})/60 ))

包量

机器网卡的平均每秒包量
采集算法:
读取/proc/net/dev文件,得到60秒内发送和接收的包量,然后除以60,得到每秒的平均包量。
shell代码:

  1. packet_be=(`awk -F'[: ]+’ ‘BEGIN{ORS=" "}/eth0/{print $4,$12}/eth1/{print $4,$12}’ /proc/net/dev`)
  2. sleep 60
  3. packet_af=(`awk -F'[: ]+’ ‘BEGIN{ORS=" "}/eth0/{print $4,$12}/eth1/{print $4,$12}’ /proc/net/dev`)
  4. eth0_in=$(( (${packet_af[0]}-${packet_be[0]})/60 ))
  5. eth0_out=$(( (${packet_af[1]}- ${packet_be[1]})/60 ))
  6. eth1_in=$(( (${packet_af[2]}- ${packet_be[2]})/60 ))
  7. eth1_out=$(( (${packet_af[3]}- ${packet_be[3]})/60 ))

shell脚本通过日志来统计网站pv 404 500状态码

下面的脚本能统计出网站的总访问量,以及404,500出现的次数。统计出来后,我们可以结合监控宝来进行记录,进而可以看出网站访问量是否异常,是否存在攻击,一目了然。还可以根据查看500出现的次数,进而判断网站程序是否出现异常。

  1. #!/bin/bash
  2. #purpose:count nginx or apache or other webserver status code using jiankongbao
  3. #how to:run the script every 5 minutes with crontab
  4. #write by zhumaohai.
  5. #blog: http://devops.webres.wang/
  6.  
  7. log_path="/var/log/nginx/devops.webres.wang/access.log"
  8. becur=`date -d "5 minute ago" +%H%M%S`
  9. code=(`tac $log_path  | awk  -v a="$becur" -v total=0 -F [‘ ‘:] ‘{
  10. t=$5$6$7
  11. if (t>=a){
  12. code[$12]++
  13. total++
  14. }
  15. else {
  16. exit;
  17. }
  18. }END{
  19. print code[404]?code[404]:0,code[500]?code[500]:0,total
  20. }’
  21. `)
  22. c404=${code[0]}
  23. c500=${code[1]}
  24. total=${code[2]}
  25. echo -e "<pre>nc404:${c404}nc500:${c500}ntotal:${total}n</pre>" > /data/www/status/devops.webres.wang.html

脚本最后一行是以:

  1. <pre>
  2. c404:1102
  3. c500:545
  4. total:55463
  5. </pre>

的格式写入到一个devops.webres.wang html文件,再结合监控宝的自定义监控来收集这些信息。
非常的方便,监控宝会自动出图表。

同时管理多台服务器的expect脚本

最近通过exploring expect书籍,简单学了下expect脚本语言,这个脚本语言是tcl语言的扩展,用来解决一些工具无法自动交互的问题,如ssh登录时,无法在命令就指定密码等。下面是利用expect来实现管理多台服务器的简单例子:

  1. #!/usr/bin/expect
  2. #purpose:auto run command on multiple servers
  3. #how to:  mms <user> <cmd>
  4. #write by zhumaohai.
  5. #blog:http://devops.webres.wang/
  6.  
  7. if {$argc < 2} {
  8. puts "usage: mms <user> <cmd>"
  9. exit 1
  10. }
  11.  
  12. #set servers
  13. set SERVERS {"192.168.0.100" "192.168.0.101" "192.168.0.102"}
  14.  
  15. #set password
  16. set PASSWORDS(user1) "passwd1"
  17. set PASSWORDS(user2) "passwd2"
  18.  
  19. #get virables
  20. set USER [lindex $argv 0]
  21. set CMD [lrange $argv 1 end]
  22.  
  23. set passwd $PASSWORDS($USER)
  24.  
  25. foreach x $SERVERS {
  26. eval spawn ssh -l $USER $x $CMD
  27. expect {
  28. "password" { send "$passwdr" }
  29. "yes/no" { send "yesr";exp_continue; }
  30. }
  31. expect eof
  32. }

1、这里定义了三台服务器192.168.0.100 192.168.0.101 192.168.0.102,定义了用户user1的密码为passwd1,用户user2的密码为passwd2,假如脚本文件名为ms,用法为:
./ms 用户 命令
如./ms user1 date
2、在使用脚本时,请确认系统已经安装有expect命令,centos使用yum install expect安装,ubuntu使用apt-get install expect安装。

expect spawn、linux expect 用法小记

使用expect实现自动登录的脚本,网上有很多,可是都没有一个明白的说明,初学者一般都是照抄、收藏。可是为什么要这么写却不知其然。本文用一个最短的例子说明脚本的原理。
  脚本代码如下:

  1.   ##############################################
  2.   #!/usr/bin/expect
  3.   set timeout 30
  4.   spawn ssh -l username 192.168.1.1
  5.   expect "password:"
  6.   send "ispassr"
  7.   interact
  8.   ##############################################

  1. [#!/usr/bin/expect]
  这一行告诉操作系统脚本里的代码使用那一个shell来执行。这里的expect其实和linux下的bash、windows下的cmd是一类东西。
  注意:这一行需要在脚本的第一行。
  2. [set timeout 30]
  基本上认识英文的都知道这是设置超时时间的,现在你只要记住他的计时单位是:秒
  3. [spawn ssh -l username 192.168.1.1]
  spawn是进入expect环境后才可以执行的expect内部命令,如果没有装expect或者直接在默认的SHELL下执行是找不到spawn命令的。所以不要用 “which spawn“之类的命令去找spawn命令。好比windows里的dir就是一个内部命令,这个命令由shell自带,你无法找到一个dir.com 或 dir.exe 的可执行文件。
  它主要的功能是给ssh运行进程加个壳,用来传递交互指令。
  4. [expect “password:”]
  这里的expect也是expect的一个内部命令,有点晕吧,expect的shell命令和内部命令是一样的,但不是一个功能,习惯就好了。这个命令的意思是判断上次输出结果里是否包含“password:”的字符串,如果有则立即返回,否则就等待一段时间后返回,这里等待时长就是前面设置的30秒
  5. [send “ispassr”]
  这里就是执行交互动作,与手工输入密码的动作等效。
  温馨提示: 命令字符串结尾别忘记加上“r”,如果出现异常等待的状态可以核查一下。
  6. [interact]
  执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行

  1.   #!/usr/bin/expect #注意安装的路径,不确定 whereis expect 一下
  2.   # Change a login shell to bash
  3.   set user [lindex $argv 0]
  4.   spawn bash $user
  5.   expect "]:"
  6.   send "/bin/bash "
  7.   expect eof
  8.   exit

转自:http://sysop.blogbus.com/logs/70787883.html

shell数组小结

数组作为一种特殊的数据结构在任何一种编程语言中都有它的一席之地,当然bash shell也不例外。本文就shell数组来做一个小的总结。
在这里只讨论一维数组的情况,关于多维数组(事实上,你得用一维数组的方法来模拟),不涉及。这里包括数组的复制,计算,删除,替换。

数组的声明:

  1. 1)array[key]=value # array[0]=one,array[1]=two
  1. 2)declare -a array # array被当作数组名
  1. 3)array=( value1 value2 value3 … )
  1. 4)array=( [1]=one [2]=two [3]=three … )
  1. 5)array="one two three" # echo ${array[0|@|*]},把array变量当作数组来处理,但数组元素只有字符串本身

数组的访问:

  1. 1)${array[key]} # ${array[1]}

数组的删除

  1. 1)unset array[1] # 删除数组中第一个元素
  1. 2)unset array # 删除整个数组

计算数组的长度:

  1. 1)${#array}
  1. 2)${#array[0]} #同上。 ${#array[*]} 、${#array[@]}。注意同#{array:0}的区别

数组的提取
从尾部开始提取:

  1. array=( [0]=one [1]=two [2]=three [3]=four )
  2. ${array[@]:1} # two three four,除掉第一个元素后所有元素,那么${array[@]:0}表示所有元素
  3. ${array[@]:0:2} # one two
  4. ${array[@]:1:2} # two three

子串删除

  1. [root@localhost dev]# echo ${array[@]:0}
  2. one two three four
  3.  
  4. [root@localhost dev]# echo ${array[@]#t*e} # 左边开始最短的匹配:"t*e",这将匹配到"thre"
  5. one two e four
  6.  
  7. [root@localhost dev]# echo ${array[@]##t*e} # 左边开始最长的匹配,这将匹配到"three"
  8.  
  9. [root@localhost dev]# array=( [0]=one [1]=two [2]=three [3]=four )
  10.  
  11. [root@localhost dev]# echo ${array[@] %o} # 从字符串的结尾开始最短的匹配
  12. one tw three four
  13.  
  14. [root@localhost dev]# echo ${array[@] %%o} # 从字符串的结尾开始最长的匹配
  15. one tw three four

子串替换

  1. [root@localhost dev]# array=( [0]=one [1]=two [2]=three [3]=four )

第一个匹配到的,会被删除

  1. [root@localhost dev]# echo ${array[@] /o/m}
  2. mne twm three fmur

所有匹配到的,都会被删除

  1. [root@localhost dev]# echo ${array[@] //o/m}
  2. mne twm three fmur

没有指定替换子串,则删除匹配到的子符

  1. [root@localhost dev]# echo ${array[@] //o/}
  2. ne tw three fur

替换字符串前端子串

  1. [root@localhost dev]# echo ${array[@] /#o/k}
  2. kne two three four

替换字符串后端子串

  1. [root@localhost dev]# echo ${array[@] /%o/k}
  2. one twk three four

转自:http://bbs.chinaunix.net/thread-1779167-1-1.html