shell脚本一例之抓阄


 Home> LiXinYu> shell脚本一例之抓阄  :2015 :Leo 转载请注明来源  阅读: 3,038 次 

本题目来自老男孩老师51cto博客,链接如下
http://oldboy.blog.51cto.com/2561410/1308647
转载请注明最原始出处!

问题如下:
有N个学生(N<99),从中选出三个去参加实践,要求通过shell脚本实现
1、执行脚本后,想去的同学输入英文名字全拼,产生随机数01-99之间的数字,数字越大就去参加项目实践,前面已经抓到的数字,下次不能在出现相同数字。
2、第一个输入名字后,屏幕输出信息,并将名字和数字记录到文件里,程序不能退出继续等待别的学生输入。

本题的解决方法有很多,我最近也是初学shell,大神轻喷!!!

首先看到题目,先要考虑本题涉及到的知识点:
1)、linux下如何取01-99的随机数,最简单的方法当然就是$RANDOM变量了
2)、shell脚本中read方式的传参。
3)、对于输入名字不能退出,可以用while循环或for循环实现,我认为本题用while最佳。
4)、对于获取到随机数大小的判断,我认为既然都输入到文件中,可以通过sort排序功能取出最大的三个值。

下面开始做这道题,我的思路是各个击破,最后再按顺序排列成一个完整的脚本
一、首先我需要一个文件来保存名字和随机数,这里可以定义一个变量,当然我还可以对这个变量进行判断,查看此文件是否存在,如果不存在就创建

file=name_file.db
if [ ! -f $file ]
  then
    touch $file
fi

二、接下来就是取出01-99的随机数了,可以通过$RANDOM变量取出的随机数除以99取余,再加1,就是1-99了,这里我把随机数赋值给一个变量

random=$(($RANDOM%99+1))

由于随机数每次取值不能和上一次重复,而每次取值后名字和随机数都会存放带上面定义好的文件中,所以我可以做如下判断,如果随机数重复了便重新取值,可以编写一个while的死循环实现,不重复就break跳出,否则就循环继续取值

  while true
  do
    random=$(($RANDOM%99+1))
    if [ -z `egrep $random $file|awk '{print $2}'` ]
      then
        break
    fi
  done

三、此时来到第三步,正题,让用户输入名字,也就是用到了read,当然,这时候我也可以对用户输入进行判断,此时有三种情况,即用户什么都没输入,用户输入了一个字符串(名字),用户输入了2个以上的字符串。而我要的只有输入一个字符串的情况,所以我可以做如下操作:

 read -p "pls write you name:" name empty

  [ ${#name} -eq 0 ]&&{
    echo "Please enter one name"
    continue
  }
  [ ${#empty} -ne 0 ]&&{
    echo "Please enter one name"
    continue
  }
  [ "$name" = "exit" ]&&{
    echo "bey dear"
    exit 0
  }

注意这里,因为最终这些东西要放到一个死循环中去不断执行,当用户输入错误传参的时候,我是不希望脚本直接结束的,而是给一个提示,提示你输错了,然后重新输入,所以用了一个continue,而用户输入exit的时候,就执行exit直接退出脚本。

四、前面我们已经拿到了用户名字$name和随机数$random,接下来要做的就是,把这两个放入我的”库” $file中,当然放入之前要先做判断,“库”里面是不是已经存在了啊!如果存在就说明我之前已经输入过这个名字了,此时就不能再次放入到“库”中了,而是要把“库”中原来的记录拿出来,所以else后面一定要是egrep $name $file(原来的random),而不要是echo “$name $random”(新生成的random)哦

if [ -z `egrep $name $file|awk '{print $1}'` ]
    then
      echo "$name $random"
      echo "$name $random" >>$file
    else
      egrep $name $file
  fi

五、现在“库”也有了,上面也把用户输入的随机数输出了,这时候我就要取出排名前三,即随机数最大的三个人,很简单,只需要一个sort排序功能

 sort -rn -k2 $file|head -3

够简单吧,此时所有要求都已完成,只需要把上面的东西按顺序攅在一起就哦了,让我们再想一下逻辑,嗯,发现一个问题,就是随机数那里,当”库”里面的值越来越多,因为新的随机数不能和原来相同,取得的随机数范围就越来越小,小到为0个时,取随机数的那个while就会彻底沦落为死循环了,所以,我在整个脚本最后加了一行

 [ `cat $file|wc -l` -eq 99 ]&&{
      exit 0
    }

就是当库的数量为99个时,此时再返回去执行取随机数的while一定会成为死循环,这个时候直接来个exit,退出就好了

上面完成,最后就是把步骤按顺序排列,该写成函数的写成函数,部分地方加上一些修饰,如echo一句话告诉用户现在输出的是什么,最终的完整脚本如下:

#!/bin/bash

file=name_file.db

if [ ! -f $file ]
  then
    touch $file
  else
    >$file 
fi

function ran_num(){
  while true
  do
    random=$(($RANDOM%99+1))
    if [ -z `egrep $random $file|awk '{print $2}'` ]
      then
        break
    fi
  done
}

function lot(){
  read -p "pls write you name:" name empty

  [ ${#name} -eq 0 ]&&{
    echo "Please enter one name"
    continue
  }
  [ ${#empty} -ne 0 ]&&{
    echo "Please enter one name"
    continue
  }
  [ "$name" = "exit" ]&&{
    echo "bey dear"
    exit 0
  }

  ran_num
  if [ -z `egrep $name $file|awk '{print $1}'` ]
    then
      echo "This time obtain random number is:"
      echo "$name $random"
      echo "$name $random" >>$file
    else
      echo "This time obtain random number is:"
      egrep $name $file
  fi
}

function output(){
  lot
  echo "The random number of the top three:"
  sort -rn -k2 $file|head -3
  [ `cat $file|wc -l` -eq 99 ]&&{
    echo "random number not have,bye dear"
    exit 0
  }
}
function main(){
  while true
  do
  output
  done
}

main

最后点评一下,本地看似简单,其实很考察基础,如随机数获取,sort排序等,基础不牢者做着就有些困难了

另外我这个取随机数的方法,因为放到while循环里,当$file中的记录越来越多时,随机数的“命中率”就会越来越低,最后只有1/99,效率有些低了,读者有更好的方法可以评论在下方分享啊!



正文部分到此结束

转载请注明原文链接 http://www.z-dig.com/the-lottery-of-shell-script-example.html

 <- 点击复制网址
 <- 点击分享