免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 89801 | 回复: 116
打印 上一主题 下一主题

ChinaUnix技术实践之四----Shell编程大赛! [复制链接]

论坛徽章:
49
15-16赛季CBA联赛之福建
日期:2016-06-22 16:22:002015年亚洲杯之中国
日期:2015-01-23 16:25:12丑牛
日期:2015-01-20 09:39:23未羊
日期:2015-01-14 23:55:57巳蛇
日期:2015-01-06 18:21:36双鱼座
日期:2015-01-02 22:04:33午马
日期:2014-11-25 09:58:35辰龙
日期:2014-11-18 10:40:07寅虎
日期:2014-11-13 22:47:15申猴
日期:2014-10-22 15:29:50摩羯座
日期:2014-08-27 10:49:43辰龙
日期:2014-08-21 10:47:58
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-05-15 23:51 |只看该作者 |倒序浏览
大赛结果公布,奖品我们会第一时间快递给各位!

http://bbs.chinaunix.net/thread-3567765-1-1.html

Shell版块是ChinaUnix社区内讨论比较热烈的技术版块之一。之前我们已经成功举办了PHP、C/C++和Perl的编程大赛,今天我们举办第四期---Shell编程大赛,发挥您的技术之长,赢取我们为优胜者准备的丰富奖品,欢迎大家踊跃参加!

第一期:PHP编程大赛 http://bbs.chinaunix.net/thread-1788191-1-1.html
第二期:C/C++编程大赛http://bbs.chinaunix.net/thread-1820953-1-1.html
第三期:Perl编程大赛http://bbs.chinaunix.net/thread-1860259-1-1.html

参赛要求:参与活动必须是chinaunix社区的注册会员

点击注册: http://sso.chinaunix.net/Register

大赛日程:

参赛时间:2011.05.15~2011.06.05

评选时间:2011.06.06~2011.06.16

结果公布:2011.06.20

奖项设置:
一等奖:3名,最先正确完成10道题的三名用户,赠送微软IE3.0复刻版鼠标一个。
二等奖:5名,,获奖者为最先正确完成8道试题的五名用户,赠送特别定制版ChinaUnix商务衬衫。
三等奖:10名,获奖者为最先正确完成6道试题的十名用户,赠送ChinaUnix 限量版水杯一个。


参赛细则:
(1)代码规范:使用各种标准shell,awk,sed,采用编程标准可以使项目更加顺利地完成。
(2)性能:应用程序可以运行与高效运行是两个层次,保证程序的最佳效率。
(3)简洁:写代码是一种艺术。除了正确的缩进、大小写、命名规则之外,请时刻牢记爱因斯坦的名言--简单就是美。
(4)每位会员可以发表多个代码,以最高评价为准,不可重复获奖;
(5)提交代码请跟帖发表,并附相关系统环境及编译环境说明。
评选获奖的依据:答题的时间及答题的质量为依据,邀请嘉宾作为评选人。

代码提交:
参赛者以跟帖的方式提交代码,相似代码以最先提交为准,谁最早提交谁优秀。
注:严禁抄袭,一经发现,取消评选资格;


大赛评委团:
waker
Shell_HAT
cjaizss
blackold

大赛联系人:
send_linux 站内联系或者qq:19286680

大赛试题:
问题1:
用最简洁的命令列出当前目录下的一级子目录,可以不包含隐藏目录(目录名以.开头的目录)


问题2:
GNU sed 提供了-i选项,为什么有人说sed -i 并不象 ed 一样真正的编辑文件?(提示:观察文件改变前后的inode)

问题3:
用shell写一个cgi脚本,提供一个简单的webmail介面,将本地的一个文件通过web服务器发送到指定的邮箱

问题4:
awk -F'' 与 awk -F '' 一样吗?


问题5:
这条语句有什么作用?
sed -if /script/scr.sedcc test.txt


问题6:
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

是如何执行的?与"#!/usr/local/bin/tclsh"相比,它有什么优点?


问题7:
#!/bin/sed -f"  shebang 后可有其它字符吗?为什么?



问题8:
GNU awk的$1=$1到底有什么作用?$0=$0呢?


问题9:
写一个shell脚本,输出CU现有的版面和相应版主,并统计有多少个版面及多少个版主。


问题10:
人机五子棋。原始规则(无禁手),最好加上标准规则,三手交换(即黑下第二手之后白可以提出交换),五手两打,黑三三禁手,黑四四禁手,黑长连禁手(超过5个子相连),逢五无禁手。白无禁手,长连也算胜。关键在于人机对下。

论坛徽章:
0
2 [报告]
发表于 2011-05-15 23:57 |只看该作者
本帖最后由 xiaopan3322 于 2011-05-16 21:46 编辑

沙发???

突然感觉自己水平好烂好烂,估计能答对一半就不错了……
总觉得第一个回答的人有点亏啊,有优惠不,哈哈……

1.
补充一个(应该还没人答过吧)。
这题我佩服SS兄,echo */这条命令用的真好,之前确实没想到……
  1. tree -d -L 1
复制代码
  1. ls -d */
复制代码
其实还有一个不算办法的办法(因为会计算大小,所以目录很大是会很慢,但是确实可以算一条简洁的命令):
  1. du --max-depth=1
复制代码
2.
区别在于交互式,因为sed只适用于非交互式的场合(可以认为这是一种弊端,因为会有临时文件产生)。
同时,使用sed -i编辑文件会导致文件的inode改变。

3.
看来我最开始的理解是对的,
Shell的cgi其实并不难,无非就是用html的语法罢了,这里有个前提,就是系统已经启动了apache:
  1. [root@hzlinea08 ~]# /opt/lampp/lampp start
  2. Starting XAMPP for Linux 1.7.4...
  3. XAMPP: Starting Apache with SSL (and PHP5)...
  4. XAMPP: Starting MySQL...
  5. XAMPP: Starting ProFTPD...
  6. XAMPP for Linux started.
  7. [root@hzlinea08 ~]# hostname              
  8. hzlinea08.china.nsn-net.net
复制代码
为了表达清楚,我在第四步附上图片:
这道题分为四个步骤:
1). 启动apache(我偷懒了,用的是lamp)
2). 准备shell脚本(位于/opt/lampp/cgi-bin,并确保此脚本有可执行权限),如下:
  1. [root@hzlinea08 cgi-bin]# pwd
  2. /opt/lampp/cgi-bin
  3. [root@hzlinea08 cgi-bin]# cat mail
  4. #!/bin/sh

  5. # Print out necessary header and empty line
  6. echo -e "Content-type: text/html\n"

  7. # Print out a title and text. Note the HTML tags in the strings.
  8. echo "<TITLE>Simple mail system</TITLE>"
  9. echo "<H1 align=center>Simple mail system</H1>"
  10. echo "<hr>"
  11. echo "<b>Mail to list: </b>xiaopan3322@gmail.com</br>"
  12. echo "<b>Mail attachment: </b>urfile</br>"
  13. if [ -e urfile ]; then
  14.     (echo "contents"; uuencode urfile file) | mail -s "subject" xiaopan3322@gmail.com
  15.     echo "<b>Sending completed at: </b>`date +"%a %b %e, %Y"`</br>"
  16. else
  17.     echo "<b></br>Error, the urfile doesn't exist!!!</br></b>"
  18. fi

  19. # Clean up HTML page. Note the ending bold tag.
  20. #echo "</b>"
  21. echo "<hr>"
  22. echo "<H1></H1>"
复制代码
3). 准备index.php(位于/opt/lampp/htdocs):
  1. [root@hzlinea08 htdocs]# pwd
  2. /opt/lampp/htdocs
  3. [root@hzlinea08 htdocs]# cat index.php
  4. <A HREF="/cgi-bin/mail?/opt/lampp/cgi-bin/mail">Click here to sending mail</A>
复制代码
4). 在任意一台能够访问此机器的机子上,敲入hostname/ip:
主界面:

发送成功界面:

发送失败界面:


4.
不一样,在这里,第一种写法有误。

5.
sed调用文件/script/scr.sedcc执行,对test.txt直接处理

6.
首先说执行过程:
  1. 第一种会导致sh和tclsh都去执行脚本,exec仅通过sh执行,sh先执行脚本,把第二行作为注释,然后执行第三行,当执行到exec的时候停止sh的处理,转而启用tclsh,这个时候tclsh会重新将整个脚本再执行一次,由于这个时候第二行末尾有个续行符,所以tclsh将所有三行都当成了注释。
复制代码
再来说优点:
第一种写法好,如果没有记错的话,好处应该有三点:

  1. 1). tclsh脚本可以位于任意位置(只要是在$PATH中,shell能找到的就行),也就是说并不需要讲绝对路径写到脚本中去
  2. 2). 它能够突破文件名为30个字符的限制
  3. 3). 这种写法甚至在tclsh本身是shell脚本的时候也能执行
复制代码


7.

起初我就感觉这道题应该写错了,更新后又仔细的看了下,这回终于理解题意了。
答案如下:
不能!!!(空格可以有)
对于Shebang lines(即#!打头的行),一般只允许在解释器后面跟一段空格,这也就是为什么所有sed的参数不能分开的应用于Shebang line的原因(比方说你不能想当然的写成#!/usr/bin/sed -E -f,因为这是不允许的)。

8.
这应该是这个动作对awk做的一次欺骗,目的就是为了让OFS生效,NF+=0也能达到同样的效果。$0=$0不能。

9.
补上,写的比较垃圾,不过功能可以实现
  1. #!/bin/bash
  2. :>moderator_num
  3. main_url="http://bbs2.chinaunix.net"
  4. wget -q "$main_url" -O index.html
  5. Total_pages=`grep -o '^<a href="forum-.*.html" >.*a>' index.html | wc -l`
  6. sub_url=(`grep -o '^<a href="forum-.*.html" >.*a>' index.html | grep -o 'forum-.*html' | tr '\n' ' '`)
  7. sub_page=(`grep -o '^<a href="forum-.*.html" >.*a>' index.html | awk -F'[<>]' '{print $3}' | tr '\n' ' '`)
  8. for (( i=0; i<${#sub_url[@]}; i++ )); do
  9.     moderator_list=(`wget -qO- $main_url/${sub_url[i]} | sed -rn '/^<p id="modedby">/{n;p}' | sed 's/<[^>]*>//g' | awk -F: '{print $2}'`)
  10.     echo ${#moderator_list[@]} >> moderator_num 2>&1
  11.     echo -e "${sub_page[i]}: ${moderator_list[@]}"
  12. done
  13. Total_moderators=`awk '{sum+=$1}END{print sum}' moderator_num`
  14. echo "Total pages of Chinaunix: $Total_pages"
  15. echo "Total moderator of Chinaunix: $Total_moderators"
复制代码
10.
这题,无条件放弃。(我居然连规则都没看懂,汗)

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:51:162015年亚洲杯之阿曼
日期:2015-04-07 20:00:59
3 [报告]
发表于 2011-05-16 00:01 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
4 [报告]
发表于 2011-05-16 00:59 |只看该作者
发现好多都不会 之前也没听说
太受打击了
之前还认为自己shell很牛

论坛徽章:
0
5 [报告]
发表于 2011-05-16 01:09 |只看该作者
回复 4# chenbin200818


    牛这个字眼都是相对的……要看和谁比……日子长了,说不定你就是第二个黑哥……

论坛徽章:
2
射手座
日期:2014-10-10 15:59:4715-16赛季CBA联赛之上海
日期:2016-03-03 10:27:14
6 [报告]
发表于 2011-05-16 05:11 |只看该作者
本帖最后由 yinyuemi 于 2011-06-22 05:42 编辑

凑凑热闹

1:
  1. echo */
复制代码
2:
因为sed -i的执行过程:先产生一个临时文件,然后把结果输出到这个文件,
最后把这个文件重命名为原来的文件,所以当用ls -i查看编辑前后的文件会看到inode值是不同的.
ed是交互式的,是真正的in-place edit.
3.

  1. #!/bin/bash
  2. echo "Content-type: text/html"
  3. read -p '输入文件名: ' subject
  4. read -p '输入邮箱地址: ' mail_address
  5. mail -s '$subject' '$mail_address'
  6. echo "done"
复制代码
4.
不一样,-F''的话awk无法解读-F变量。
5.
--sed执行脚本(-f)/script/scr.sedcc,直接编辑修改(-i)test.txt--这道题彻底失败,想当然了
想大家学习!
6.
不知道
7.
不可以,会报错,
-f后面的会错误地被解释为文件名
8.
$1=$1可以使OFS生效,$0=$0可以使FS生效。

  1. echo '1 1 1
  2. 2 2 2' |awk 'NR==1{OFS=":";$1=$1;print}NR==2{OFS="#";$1=$1;print}'
  3. 1:1:1
  4. 2#2#2

  5. echo '1 1 1
  6. 2 2 2' |awk 'NR==1{OFS=":";$0=$0;print}NR==2{OFS="#";$0=$0;print}'
  7. 1 1 1
  8. 2 2 2


  9. echo '1:1:1
  10. 2#2#2' |awk 'NR==1{FS=":";$1=$1;print $1}NR==2{FS="#";$1=$1;print $1}'
  11. 1:1:1
  12. 2#2#2

  13. echo '1:1:1
  14. 2#2#2' |awk 'NR==1{FS=":";$0=$0;print $1}NR==2{FS="#";$0=$0;print $1}'
  15. 1
  16. 2
复制代码
9.

  1. ./script.sh >outputfile


  2. cat script.sh

  3. #!/bin/bash
  4. wget -qO- "http://bbs.chinaunix.net/index.shtml" |\
  5. awk '/^<a.*href.*forum.*html" >/{sub(/<a href="/,"http://bbs.chinaunix.net/");gsub(/" >|<\/a>/," ");print}' |\
  6. while read line1 line2
  7. do
  8. wget -qO- $line1 |\
  9. awk '/^<p id="modedby">/{getline line;gsub(/<[^>]*>|,/,"",line);printf "'"$line2"': ";print line }'
  10. done |\
  11. awk -F: '{print; {if($NF!~/\*$/) {s=split($NF,a," ");for(i=1;i<=s;i++) b[a[i]]} else {t++;z=z?z" "$1:$1}}}END{print "统计结果: CU共有"NR"个版面, "length(b)"个版主, 其中有"t"个版面的斑竹空缺,分别是\""z"\""}'
复制代码
10.
有时间的话再试试

论坛徽章:
1
巳蛇
日期:2013-10-28 15:55:33
7 [报告]
发表于 2011-05-16 08:02 |只看该作者
我自认功力不足...

不过第一题怎么没人 ls */

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
8 [报告]
发表于 2011-05-16 08:37 |只看该作者
俺再解释一下问题三吧,回答过的可以重新回答

本地是指客户端机器,CGI脚本由web服务器运行,二者在逻辑上不是同一机器
这个cgi脚本的目的是让用户可以通过浏览器将自己机器上的文件发给他人,就象gmail web介面的附件功能一样,介面和功能可以简化,但上传文件和发送文件的步骤要体现出来

论坛徽章:
0
9 [报告]
发表于 2011-05-16 08:47 |只看该作者
其实有点想做最后一题,可是老板在后面虎视眈眈,就算了,今晚再来看看

论坛徽章:
0
10 [报告]
发表于 2011-05-16 09:14 |只看该作者
本帖最后由 xinyv 于 2011-06-02 11:59 编辑

1.
  1. find ./* -maxdepth 0 -type d
复制代码
2.

  1. 通过跟踪可以看到    ed  的操作过程是
  2. write(4, "a\n1\n", 4)
  3. close(4)
  4. 通过跟踪可以看到  sed  的操作过程是 rename("./sed6wKWPx", "aa")
复制代码
总结: ed 是直接编辑文件,sed 是生成临时文件,然后改名实现的。
3.

  1. #!/bin/bash
  2. echo -e "Content-type: text/html\n"

  3. if (( $# == 0 ));then
  4. # main
  5. cat <<EOF
  6. <HTML>
  7.   <H1><center>$(date +%F) 简单发送邮件CGI</center></H1>
  8.   <HR>
  9.      <form action="${HTTP_REFERER}?send" method="POST" enctype="multipart/form-data">
  10.        <p align="left">
  11.        收件人:&nbsp<input type="text"  name="Address" size="60"><br><br>
  12.        标&nbsp&nbsp&nbsp&nbsp题:&nbsp<input type="text"  name="Subject" size="60"><br><br>
  13.        正&nbsp&nbsp&nbsp&nbsp文:&nbsp<textarea rows="10" name="Info" cols="50"></textarea><br><br>
  14.        附&nbsp&nbsp&nbsp&nbsp件:&nbsp<input type="file" name="mf" size=51/><br><br>
  15.        <input type=submit value="send"><input type="reset" value="Clear"> </p>
  16.      </form>
  17.   <HR>
  18. </HTML>
  19. EOF
  20. else
  21.     if [[ ${QUERY_STRING} == "send" ]] && [[ ${REQUEST_METHOD} = POST ]];then
  22.         cd /tmp
  23.         cat - >/tmp/$.mf
  24.         typeset -x _F=$(awk '{if($0~/^Content-Disposition.+filename/)print gensub(".+filename=\"(.+)\".*","\\1","g",$0)}' $.mf)
  25.         typeset -x State="${CONTENT_TYPE##*=}"
  26.         if [ ! -z ${_F} ];then
  27.             typeset -x $(awk 'BEGIN{FS="\r\n";RS=ENVIRON["State"]}{if($2~/Address/)print "rcptto=\x22"$4"\x22";
  28.                                                   if($2~/Subject/)print "subject=\x22"$4"\x22"
  29.                                                   if($2~/Info/)print "info=\x22"$4"\x22"
  30.                                                   if($2~/filename/)printf("%s",$5)>ENVIRON["_F"]
  31.                                    }' $.mf)
  32.             echo "${info}"|mutt -a ${_F} -s "${subject}" ${rcptto}
  33.         else
  34.             echo "${info}"|mutt -s "${subject}" ${rcptto}
  35.         fi
  36.         rm -f $.mf ${_F}
  37.     fi
  38.     cat <<EOF
  39. <HTML>
  40.   <H1><center>$(date +%F) 简单发送邮件CGI</center></H1>
  41.   <HR>
  42.   <H2><center>邮件已经发送,请查收.</center></H2>
  43.   <head>
  44.       <title>Redirect</title>
  45.       <meta http-equiv="refresh" content="2;url=${HTTP_REFERER}">
  46.   </head>
  47.   <HR>
  48. </html>
  49. EOF
  50. fi
复制代码
4.

  1. awk -F '' 可以使用 NULL 为分隔符。
  2. awk -F''  不能使用 NULL 为分隔符。起引号内必须赋值.  
复制代码
5.

  1. 按照脚本 scr.sedcc 修改 text.txt 文件。
复制代码
6.

  1. 这是 tclsh 帮助里的一段话,看过 tclsh 帮助的童鞋们应该都不陌生。

  2. 这有三个好处
  3. 1、bash 可以在路径搜索二进制文件存放位置。
  4. 2、文件名没有30个字符的限制
  5. 3、tclsh 可以直接运行脚本把 第二行的  \ 当成转义
复制代码
7.

  1. 不可以,sed 会把后面紧着的当文件名处理,当然空格例外。
复制代码
8.

  1. $1=$1 用当前的OFS重构 $0      NF 不改变
  2. $0=$0 用当前的 FS重构 $1..$N  NF 会改变
复制代码
9.有两个版打不开,没权限,所以无法统计那两个版面的版主:[频道交流区、版主会议室]
   版主里面有个叫"CU管理员" 的占算一名版主名额。

  1. #!/bin/bash
  2. #
  3. PATH=${PATH}:/sbin:/usr/sbin:/usr/local/bin
  4. Url="http://bbs.chinaunix.net"
  5. N=0
  6. curl --connect-timeout 10 -m 60 --retry 5 -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" ${Url} -o /tmp/tempfile 2>/dev/null
  7. awk '{if($0~"bold subject"){getline;getline;printf("%s %s\n",gensub("href..(.+)\"","\\1","g",$2),gensub(">|<|/a","","g",$3))}}' /tmp/tempfile >/tmp/tempfile1
  8. while read Url1 Name;do
  9.     let N++
  10.     printf "%-2s -- %-20s%-20s\n" ${N} ${Name} "[${Url}/${Url1}]" >>/tmp/tempfile3
  11.     curl --connect-timeout 10 -m 60 --retry 5 -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" ${Url}/${Url1} -o /tmp/tempfile2 2>/dev/null
  12.     awk 'BEGIN{FS="[<>]"}{if($1=="版主: ")for(i=3;i<NF;i+=4)print "版主: "$i}' /tmp/tempfile2 >>/tmp/tempfile3
  13. done</tmp/tempfile1
  14. awk '{printf("%-15s",($1=="版主:")?"["$2"] ":"\n\n"$0"\n")}' /tmp/tempfile3
  15. echo '#------------------------------------------------------------------#'
  16. awk '{if($0~/^版主/){A[$0]++}else{B[$0++]}}END{printf("CU现有版面[%d]\t版主[%d]个\n",length(B),length(A))}' /tmp/tempfile3
  17. rm -f /tmp/tempfile*
复制代码
10.

  1. #!/bin/bash
  2. PATH=${PATH}:/sbin:/usr/sbin:/usr/local/bin
  3. export E33="^[[" Y_X=(20 30) Color _Color Pie=$(echo -e "  ")

  4. function create_box() {
  5.   typeset y x
  6.   for ((y=10;y<=30;y++));do
  7.     for ((x=10;x<=50;x+=2));do
  8.       if (( x==10 )) || (( y==10 )) || (( x==50 )) || (( y==30 ));then
  9.         echo -e "${E33}${y};${x}H${E33}43m  ${E33}49m\n"
  10.       else
  11.         if (( y%2==1 ));then
  12.           typeset C1=47 C2=49
  13.         else
  14.           typeset C1=49 C2=47
  15.         fi
  16.         if (( x%4==0 ));then
  17.           echo -e "${E33}${y};${x}H${E33}${C1}m${Pie}${E33}${C2}m${Pie:-  }${E33}49m";
  18.           export box_${y}_${x}=${C1} box_${y}_$((x+2))=${C2}
  19.         fi
  20.       fi
  21.     done
  22.   done
  23.   return 0
  24. }
  25. function _Display() {
  26.   if (( $# == 3 ));then
  27.     O_color=box_${Y_X[0]}_${Y_X[1]}
  28.     echo -e "${E33}${Y_X[0]};${Y_X[1]}H${E33}${!O_color}m${Pie}${E33}49m"
  29.     case "$3" in
  30.       A)
  31.       (( --Y_X[0]<11 )) && ((Y_X[0]++))
  32.       ;;
  33.       B)
  34.       (( ++Y_X[0]>29 )) && ((Y_X[0]--))
  35.       ;;
  36.       C)
  37.       (( (Y_X[1]+=2)>48 )) && ((Y_X[1]-=2))
  38.       ;;
  39.       D)
  40.       (( (Y_X[1]-=2)<12 )) && ((Y_X[1]+=2))
  41.       ;;
  42.     esac
  43.     echo -e "${E33}${Y_X[0]};${Y_X[1]}H${E33}46m${Pie}${E33}49m"
  44.   fi
  45.   return 0
  46. }
  47. function control() {
  48.   while true;do
  49.     read -s -n1 _T 2>/dev/null
  50.     INPUT3=${INPUT2}
  51.     INPUT2=${INPUT1}
  52.     INPUT1=${_T}
  53.     if [[ "${INPUT3}${INPUT2}${INPUT1}" =~ "${E33}"[ABCD] ]];then
  54.       _Display ${Y_X[@]} ${INPUT1}
  55.     elif [[ "[${_T}]" == "[]" ]];then
  56.       O_color=box_${Y_X[0]}_${Y_X[1]}
  57.       if [[ "${!O_color}" == 4[79] ]];then
  58.         export box_${Y_X[0]}_${Y_X[1]}=42
  59.         echo -e "${E33}${Y_X[0]};${Y_X[1]}H${E33}${!O_color}m${Pie:-  }${E33}49m"
  60.         Check box_${Y_X[0]}_${Y_X[1]}
  61.         if [ $? != 0 ];then Exit;fi
  62.         AI
  63.       fi
  64.     elif [[ "${_T}" == [Qq] ]];then Exit;fi
  65.   done
  66.   return 0
  67. }
  68. function Check() {
  69.   Color=${!1}
  70.   for h in 0 1 3 2;do
  71.     j=0
  72.     for i in -4 -3 -2 -1 0 1 2 3 4 ;do
  73.       if (( h > 1 ));then
  74.         _Color="box_$((Y_X[0]+i*$((2*h-5))))_$((Y_X[1]+2*i*$(((2*h-5)**2))))"
  75.       else
  76.         _Color="box_$((Y_X[0]+i*${h}))_$((Y_X[1]+2*i*$((! h))))"
  77.       fi
  78.       if [[ "${!_Color:-43}" == "${Color}" ]];then
  79.         if (( ++j == 5 ));then
  80.           if (( h > 1 ));then
  81.             for ((k=i;k>i-5;k--));do
  82.               echo -e "${E33}$((Y_X[0]+k*$((2*h-5))));$((Y_X[1]+2*k*$(((2*h-5)**2))))H${E33}${Color}m${E33}5m[]${E33}25m"
  83.             done
  84.           else
  85.             for ((k=i;k>i-5;k--));do
  86.               echo -e "${E33}$((Y_X[0]+k*${h}));$((Y_X[1]+2*k*$((! h))))H${E33}${Color}m${E33}5m[]${E33}25m"
  87.             done
  88.           fi
  89.           return ${Color}
  90.         fi
  91.       else
  92.         j=0
  93.       fi
  94.     done
  95.   done
  96.   return 0
  97. }
  98. function weight5() {
  99.   for Color in 41 42;do
  100.     for h in 0 1 3 2;do
  101.       j=0
  102.       for i in -4 -3 -2 -1 1 2 3 4 ;do
  103.         if (( h > 1 ));then
  104.           _Color="box_$((Y_X[0]+i*$((2*h-5))))_$((Y_X[1]+2*i*$(((2*h-5)**2))))"
  105.         else
  106.           _Color="box_$((Y_X[0]+i*${h}))_$((Y_X[1]+2*i*$((! h))))"
  107.         fi
  108.         if [[ "${!_Color:-43}" == "${Color}" ]];then
  109.           if (( ++j == 4 ));then return ${Color};fi
  110.         else
  111.           j=0
  112.         fi
  113.       done
  114.     done
  115.   done
  116.   return 0
  117. }
  118. function weight4() {
  119.   for Color in 41 42;do
  120.     for h in 0 1 3 2;do
  121.       j=0;k=0
  122.       for i in -3 -2 -1 1 2 3 ;do
  123.         if (( h > 1 ));then
  124.           _Color="box_$((Y_X[0]+i*$((2*h-5))))_$((Y_X[1]+2*i*$(((2*h-5)**2))))"
  125.         else
  126.           _Color="box_$((Y_X[0]+i*${h}))_$((Y_X[1]+2*i*$((! h))))"
  127.         fi
  128.         if [[ "${!_Color:-43}" == "${Color}" ]];then
  129.           if (( ++j == 3 ));then
  130.             if (( h > 1 ));then
  131.               ((i++))
  132.               _Color="box_$((Y_X[0]+i*$((2*h-5))))_$((Y_X[1]+2*i*$(((2*h-5)**2))))"
  133.               if [[ "${!_Color}" != 4[79] ]];then let Color+=2;fi
  134.               ((i-=5))
  135.               _Color="box_$((Y_X[0]+i*$((2*h-5))))_$((Y_X[1]+2*i*$(((2*h-5)**2))))"
  136.               if [[ "${!_Color}" != 4[79] ]];then let Color+=2;fi
  137.             else
  138.               ((i++))
  139.               _Color="box_$((Y_X[0]+i*${h}))_$((Y_X[1]+2*i*$((! h))))"
  140.               if [[ "${!_Color}" != 4[79] ]];then let Color+=2;fi
  141.               ((i-=5))
  142.               _Color="box_$((Y_X[0]+i*${h}))_$((Y_X[1]+2*i*$((! h))))"
  143.               if [[ "${!_Color}" != 4[79] ]];then let Color+=2;fi
  144.             fi
  145.             [[ "${Color}" != 4[56] ]] && return ${Color}
  146.           fi
  147.         elif [[ "${!_Color:-43}" == 4[79] ]] && (( k == 0 ));then
  148.           k=1
  149.           continue
  150.         else
  151.           j=0;k=0
  152.         fi
  153.       done
  154.     done
  155.   done
  156.   return 0
  157. }

  158. function weight() {
  159.   export Color=42 _SW
  160.   (( Y_X[1] > 30 )) && _SW=$((24-Y_X[1]/2)) || _SW=$((Y_X[1]/2-6))
  161.   (( Y_X[0] > 20 )) && _SW=$(((_SW+29-Y_X[0])/2)) || _SW=$(((_SW+Y_X[0]-11)/2))
  162.   for h in 0 1 3 2;do
  163.     for i in -2 -1 1 2 ;do
  164.       if (( h > 1 ));then
  165.         _Color="box_$((Y_X[0]+i*$((2*h-5))))_$((Y_X[1]+2*i*$(((2*h-5)**2))))"
  166.       else
  167.         _Color="box_$((Y_X[0]+i*${h}))_$((Y_X[1]+2*i*$((! h))))"
  168.       fi
  169.       if [[ "${!_Color:-43}" == 42 ]];then
  170.         ((_SW+=1000))
  171.       elif [[ "${!_Color:-43}" == 4[79] ]];then
  172.         ((_SW+=100))
  173.       else
  174.         ((_SW-=300))
  175.       fi
  176.     done
  177.   done
  178. }
  179. function AI() {
  180.   export Old_Y_X=(0 0) Max=(1 0 0)
  181.   Old_Y_X=(${Y_X[@]})
  182.   for ((y=10;y<30;y++));do
  183.     for ((x=10;x<50;x+=2));do
  184.       _Color="box_${y}_${x}"
  185.       if [[ "${!_Color}" == 4[79] ]];then
  186.         Y_X=(${y} ${x})
  187.         (( Y_X[1] > 30 )) && _W=$((24-Y_X[1]/2)) || _W=$((Y_X[1]/2-6))
  188.         (( Y_X[0] > 20 )) && _W=$(((_W+29-Y_X[0])/2)) || _W=$(((_W+Y_X[0]-11)/2))
  189.         if ! $(weight5);then
  190.           if (( Max[0] < $((99999-$?*10)) ));then
  191.             Max=("$((99999-$?*10))" "${Y_X[0]}" "${Y_X[1]}")
  192.             continue
  193.           fi
  194.         elif ! $(weight4);then
  195.           _B=$?
  196.           if [[ ${_B} == 4[34] ]];then ((_B/=2));fi
  197.           if (( Max[0] < $((50000+_W-${_B}*100)) ));then
  198.             Max=("$((50000+_W-${_B}*100))" "${Y_X[0]}" "${Y_X[1]}")
  199.             continue
  200.           fi
  201.         fi
  202.       fi
  203.     done
  204.   done
  205.   Y_X=(${Old_Y_X[@]})
  206.   for h in 0 1 3 2;do
  207.     for i in -1 1 ;do
  208.       if (( h > 1 ));then
  209.         _Color="box_$((Old_Y_X[0]+i*$((2*h-5))))_$((Old_Y_X[1]+2*i*$(((2*h-5)**2))))"
  210.         Y_X=($((Old_Y_X[0]+i*$((2*h-5)))) $((Old_Y_X[1]+2*i*$(((2*h-5)**2)))))
  211.       else
  212.         _Color="box_$((Old_Y_X[0]+i*${h}))_$((Old_Y_X[1]+2*i*$((! h))))"
  213.         Y_X=($((Old_Y_X[0]+i*${h})) $((Old_Y_X[1]+2*i*$((! h)))))
  214.       fi
  215.       if [[ "${!_Color:-43}" == 4[79] ]];then
  216.         weight box_${Y_X[0]}_${Y_X[1]}
  217.         if (( Max[1] == Y_X[0] )) && (( Max[2] == Y_X[1] ));then
  218.           ((Max[0]+=_SW))
  219.         fi
  220.         if (( Max[0] < _SW ));then
  221.           Max=("${_SW}" "${Y_X[0]}" "${Y_X[1]}")
  222.         fi
  223.       fi
  224.     done
  225.   done
  226.   Y_X=("${Max[1]}" "${Max[2]}")
  227.   export box_${Y_X[0]}_${Y_X[1]}=41
  228.   echo -e "${E33}${Y_X[0]};${Y_X[1]}H${E33}41m[]${E33}49m"
  229.   Check box_${Y_X[0]}_${Y_X[1]}
  230.   if [ $? != 0 ];then Exit;fi
  231.   return 0
  232. }
  233. function Exit() {
  234.   stty echo
  235.   echo -e "${E33}35;0H${E33}49m${E33}39m${E33}?25h\n"
  236.   exit 0
  237. }

  238. # main
  239. trap 'Exit' 0 1 2 3 15 22 24
  240. stty -echo
  241. echo -e "${E33}?25l${E33}2J"
  242. create_box
  243. echo -e "${E33}${Y_X[0]};${Y_X[1]}H${E33}46m${Pie}${E33}49m"
  244. control
  245. exit 0

复制代码
人机对战那部分真的不好写,这个还算凑合能玩,方向键控制移动光标,空格键下子,落子后请耐心等待电脑落子,电脑落子后才可以继续移动光标。
没加任何禁手和其他的规则,就是看谁先连出五子,有时间在慢慢完善吧,这几天功夫也就写这么个玩意啦。

特别提示: 如果你复制网页上面的脚本不能运行,请用如下方法解决。
1、 复制网页上面的代码,保存成一个文件。 urfile
2、 去掉掉多余的空格。( sed 's/^    //' -i urfile)
3、 编辑脚本第三行 E33 变量 为 ^[[ ,注意这里面的第一个 ^[ 的输入方法是 (按住 ctrl 不放,然后按 v 在按 [ 后放开 ctrl ) 就是 ctrl-v + ctrl-[
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP