六试Ubuntu-Shell脚本

随意读:

Linux Kernel 4.3发布,4.4将会是LTS版本 - Linux 4.3

程序员崩溃:2.55乘100结果竟不是255 - 二进制


Shell本身是一个用C语言编写的程序,它是用户使用Unix/Linux的桥梁,用户的大部分工作都是通过Shell完成的。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。

它虽然不是Unix/Linux系统内核的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其使用方法,是用好Unix/Linux系统的关键。

下面介绍两个有意思的shell命令

1. 循环广播(广播轰炸)

#!/bin/sh

while true

do

echo wall hi

done

执行以上shell命令,只要电脑连接一台服务器,就可以无限度广播下去,按Ctrl+C即可终止。稍加修改

#!/bin/sh

while true

do

echo write 6000 hi

done

即可指定对一个人推送消息(以此来报复)

2. shell脚本上的俄罗斯方块(Linux下shell脚本制作俄罗斯方块游戏 )

将网站内代码复制到 .sh 脚本中随后运行

就可以体验一下阔别依旧的俄罗斯方块了。

此外还有许多shell下的小游戏例如扫雷一类的,大家可以自己搜搜看



参考来源:

Linux Shell脚本教程:30分钟玩转Shell脚本编程_Shell中文网

#!/bin/bash

# Tetris Game

# 10.21.2003 xhchen< [email]xhchen@winbond.com.tw[/email]>

#APP declaration

APP_NAME="${0##*[\\/]}"

APP_VERSION="1.0"

#颜色定义

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=(00011011)

box1=(0212223210111213)

box2=(0001111201101120)

box3=(0102101100101121)

box4=(01021121101112220111202100101112)

box5=(01112122101112200001112102101112)

box6=(01111221101112210110112101101112)

#所有其中方块的定义都放到box变量中

box=(${box0[@]}${box1[@]}${box2[@]}${box3[@]}${box4[@]}${box5[@]}${box6[@]})

#各种方块旋转后可能的样式数目

countBox=(1222444)

#各种方块再box数组中的偏移

offsetBox=(013571115)

#每提高一个速度级需要积累的分数

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

#接收输入的进程的主函数

functionRunAsKeyReceiver()

{

localpidDisplayerkeyaKeysigcESCsTTY

pidDisplayer=$1

aKey=(000)

cESC=`echo-ne"\033"`

cSpace=`echo-ne"\040"`

#保存终端属性。在read -s读取终端键时,终端的属性会被暂时改变。

#如果在read -s时程序被不幸杀掉,可能会导致终端混乱,

#需要在程序退出时恢复终端属性。

sTTY=`stty-g`

#捕捉退出信号

trap"MyExit;"INTTERM

trap"MyExitNoSub;"$sigExit

#隐藏光标

echo-ne"\033[?25l"

while:

do

#读取输入。注-s不回显,-n读到一个字符立即返回

read-s-n1key

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"]];thensig=$sigRotate#<向上键>

elif[[$key=="B"]];thensig=$sigDown#< 向下键>

elif[[$key=="D"]];thensig=$sigLeft#< 向左键>

elif[[$key=="C"]];thensig=$sigRight#< 向右键>

fi

elif[[$key=="W"||$key=="w"]];thensig=$sigRotate#W, w

elif[[$key=="S"||$key=="s"]];thensig=$sigDown#S, s

elif[[$key=="A"||$key=="a"]];thensig=$sigLeft#A, a

elif[[$key=="D"||$key=="d"]];thensig=$sigRight#D, d

elif[["[$key]"=="[]"]];thensig=$sigAllDown#空格键

elif[[$key=="Q"||$key=="q"]]#Q, q

then

MyExit

fi

if[[$sig!=0]]

then

#向另一进程发送消息

kill-$sig$pidDisplayer

fi

done

}

#退出前的恢复

functionMyExitNoSub()

{

localy

#恢复终端属性

stty$sTTY

((y=iTop+iTrayHeight+4))

#显示光标

echo-e"\033[?25h\033[${y};0H"

exit

}

functionMyExit()

{

#通知显示进程需要退出

kill-$sigExit$pidDisplayer

MyExitNoSub

}

#处理显示和游戏流程的主函数

functionRunAsDisplayer()

{

localsigThis

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:

do

#根据当前的速度级iLevel不同,设定相应的循环的次数

for((i=0;i<21-iLevel;i++))

do

sleep0.02

sigThis=$sig

sig=0

#根据sig变量判断是否接受到相应的信号

if((sigThis==sigRotate));thenBoxRotate;#旋转

elif((sigThis==sigLeft));thenBoxLeft;#左移一列

elif((sigThis==sigRight));thenBoxRight;#右移一列

elif((sigThis==sigDown));thenBoxDown;#下落一行

elif((sigThis==sigAllDown));thenBoxAllDown;#下落到底

fi

done

#kill -$sigDown $$

BoxDown#下落一行

done

}

#BoxMove(y, x), 测试是否可以把移动中的方块移到(x, y)的位置, 返回0则可以, 1不可以

functionBoxMove()

{

localjixyxTestyTest

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

#撞到墙壁了

return1

fi

if((${iMap[y*iTrayWidth+x]}!=-1))

then

#撞到其他已经存在的方块了

return1

fi

done

return0;

}

#将当前移动中的方块放到背景方块中去,

#并计算新的分数和速度级。(即一次方块落到底部)

functionBox2Map()

{

localjixyxpypline

#将当前移动中的方块放到背景方块中去

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

do

for((i=j+iTrayWidth-1;i>=j;i--))

do

if((${iMap[$i]}==-1));thenbreak;fi

done

if((i>=j));thencontinue;fi

((line++))

for((i=j-1;i>=0;i--))

do

((x=i+iTrayWidth))

iMap[$x]=${iMap[$i]}

done

for((i=0;i

do

iMap[$i]=-1

done

done

if((line==0));thenreturn;fi

#根据消去的行数line计算分数和速度级

((x=iLeft+iTrayWidth*2+7))

((y=iTop+11))

((iScore+=line*2-1))

#显示新的分数

echo-ne"\033[1m\033[3${cScoreValue}m\033[${y};${x}H${iScore}         "

if((iScore%iScoreEachLevel

then

if((iLevel<20))

then

((iLevel++))

((y=iTop+14))

#显示新的速度级

echo-ne"\033[3${cScoreValue}m\033[${y};${x}H${iLevel}        "

fi

fi

echo-ne"\033[0m"

#重新显示背景方块

for((y=0;y

do

((yp=y+iTrayTop+1))

((xp=iTrayLeft+1))

((i=y*iTrayWidth))

echo-ne"\033[${yp};${xp}H"

for((x=0;x

do

((j=i+x))

if((${iMap[$j]}==-1))

then

echo-ne"  "

else

echo-ne"\033[1m\033[7m\033[3${iMap[$j]}m\033[4${iMap[$j]}m[]\033[0m"

fi

done

done

}

#下落一行

functionBoxDown()

{

localys

((y=boxCurY+1))#新的y坐标

ifBoxMove$y$boxCurX#测试是否可以下落一行

then

s="`DrawCurBox 0`"#将旧的方块抹去

((boxCurY=y))

s="$s`DrawCurBox 1`"#显示新的下落后方块

echo-ne$s

else

#走到这儿, 如果不能下落了

Box2Map#将当前移动中的方块贴到背景方块中

RandomBox#产生新的方块

fi

}

#左移一列

functionBoxLeft()

{

localxs

((x=boxCurX-1))

ifBoxMove$boxCurY$x

then

s=`DrawCurBox0`

((boxCurX=x))

s=$s`DrawCurBox1`

echo-ne$s

fi

}

#右移一列

functionBoxRight()

{

localxs

((x=boxCurX+1))

ifBoxMove$boxCurY$x

then

s=`DrawCurBox0`

((boxCurX=x))

s=$s`DrawCurBox1`

echo-ne$s

fi

}

#下落到底

functionBoxAllDown()

{

localkjixyiDowns

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

do

((i=k*iTrayWidth+x))

if((${iMap[$i]}!=-1));thenbreak;fi

done

((k-=y+1))

if(($iDown>$k));theniDown=$k;fi

done

s=`DrawCurBox0`#将旧的方块抹去

((boxCurY+=iDown))

s=$s`DrawCurBox1`#显示新的下落后的方块

echo-ne$s

Box2Map#将当前移动中的方块贴到背景方块中

RandomBox#产生新的方块

}

#旋转方块

functionBoxRotate()

{

localiCountiTestRotateboxTestjis

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

ifBoxMove$boxCurY$boxCurX#测试旋转后是否有空间放的下

then

#抹去旧的方块

for((j=0;j<8;j++))

do

boxCur[$j]=${boxTest[$j]}

done

s=`DrawCurBox0`

#画上新的方块

for((j=0,i=(${offsetBox[$iBoxCurType]}+$iTestRotate)*8;j<8;j++,i++))

do

boxCur[$j]=${box[$i]}

done

s=$s`DrawCurBox1`

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, 抹去方块。

functionDrawCurBox()

{

localijtbDrawsBoxs

bDraw=$1

s=""

if((bDraw==0))

then

sBox="\040\040"

else

sBox="[]"

s=$s"\033[1m\033[7m\033[3${cBoxCur}m\033[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]})))

#\033[y;xH, 光标到(x, y)处

s=$s"\033[${i};${t}H${sBox}"

done

s=$s"\033[0m"

echo-n$s

}

#更新新的方块

functionRandomBox()

{

localijt

#更新当前移动的方块

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]}

done

((boxCurY=-t))

for((j=1,i=-4,t=20;j<8;j+=2))

do

if((${boxCur[$j]}>i));theni=${boxCur[$j]};fi

if((${boxCur[$j]}

done

((boxCurX=(iTrayWidth-1-i-t)/2))

#显示当前移动的方块

echo-ne`DrawCurBox1`

#如果方块一出来就没处放,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"\033[${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"\033[1m\033[7m\033[3${cBoxNew}m\033[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"\033[${i};${t}H[]"

done

echo-ne"\033[0m"

}

#初始绘制

functionInitDraw()

{

clear

RandomBox#随机产生方块,这时右边预显示窗口中有方快了

RandomBox#再随机产生方块,右边预显示窗口中的方块被更新,原先的方块将开始下落

localit1t2t3

#显示边框

echo-ne"\033[1m"

echo-ne"\033[3${cBorder}m\033[4${cBorder}m"

((t2=iLeft+1))

((t3=iLeft+iTrayWidth*2+3))

for((i=0;i

do

((t1=i+iTop+2))

echo-ne"\033[${t1};${t2}H||"

echo-ne"\033[${t1};${t3}H||"

done

((t2=iTop+iTrayHeight+2))

for((i=0;i

do

((t1=i*2+iLeft+1))

echo-ne"\033[${iTrayTop};${t1}H=="

echo-ne"\033[${t2};${t1}H=="

done

echo-ne"\033[0m"

#显示"Score"和"Level"字样

echo-ne"\033[1m"

((t1=iLeft+iTrayWidth*2+7))

((t2=iTop+10))

echo-ne"\033[3${cScore}m\033[${t2};${t1}HScore"

((t2=iTop+11))

echo-ne"\033[3${cScoreValue}m\033[${t2};${t1}H${iScore}"

((t2=iTop+13))

echo-ne"\033[3${cScore}m\033[${t2};${t1}HLevel"

((t2=iTop+14))

echo-ne"\033[3${cScoreValue}m\033[${t2};${t1}H${iLevel}"

echo-ne"\033[0m"

}

#退出时显示GameOVer!

functionShowExit()

{

localy

((y=iTrayHeight+iTrayTop+3))

echo-e"\033[${y};0HGameOver!\033[0m"

exit

}

#显示用法.

functionUsage

{

cat<

Usage:$APP_NAME

Starttetrisgame.

-h,--helpdisplaythishelpandexit

--versionoutputversioninformationandexit

EOF

}

#游戏主程序在这儿开始.

if[["$1"=="-h"||"$1"=="--help"]];then

Usage

elif[["$1"=="--version"]];then

echo"$APP_NAME $APP_VERSION"

elif[["$1"=="--show"]];then

#当发现具有参数--show时,运行显示函数

RunAsDisplayer

else

bash$0--show&#以参数--show将本程序再运行一遍

RunAsKeyReceiver$!#以上一行产生的进程的进程号作为参数

fi

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 1.创建文件夹 !/bin/sh mkdir -m 777 "%%1" 2.创建文件 !/bin/sh touch...
    BigJeffWang阅读 9,834评论 3 53
  • 基础命令 主要的命令和快捷键 Linux系统命令由三部分组成:cmd + [options]+[operation...
    485b1aca799e阅读 1,016评论 0 0
  • 个人学习批处理的初衷来源于实际工作;在某个迭代版本有个BS(安卓手游模拟器)大需求,从而在测试过程中就重复涉及到...
    Luckykailiu阅读 4,533评论 0 11
  • 0.linux启动的步骤 设备加电----》BIOS自检-----》grub引导启动-----》加载内核----》...
    萌面大叔2阅读 740评论 0 1
  • 【壹】 曲径通幽处 , 禅房花木深。 小和尚是被禅院里的老和尚在街角的竹筐中寻到的,他清脆的哭声让原本犹豫的老和尚...
    Z47Alinanana阅读 566评论 0 0