初学Linux——Day10——shell脚本的编写心得

    写了几天的学习笔记,今天更新一个自己写的一个脚本的心得,作为有个初学者,写出一个脚本都很难,上周老师讲解了Linux的shell脚本的基本知识,今天闲来无事,就自己结合自己C++的知识,写了一个小小的shell脚本,因为对shell的语法不熟悉,有很多不懂的,通过查阅资料基本达成了自己原来设定的目标。

    先来描述一下我写的脚本,我这次写的是随机猜数,设定一个最大值,然后随机生成一个符合范围的随机数,用户再猜测一个数,判定输入合法后进行比较,然后反馈给用户数值的大小关系,不断循环知道用户猜对了。

    OK,为了让大家更清楚了解,我运行演示一下:

Lyu的shell展示

    这是我写的脚本的运行情况,下面我按功能模块一个一个来讲一下我的脚本


一、核心模块

    该程序的核心,就是生成一个随机数,然后进行大小比较,以及一个循环。

    首先,先说说随机数怎么搞,在shell脚本里面,有个环境变量:$RANDOM,这个变量随时代表一个0-32767随机数,因为我们有范围,所以我们要把随机数设置在一个范围内,这时候就要用到取余运算,他的计算的方式就是,经过将两数做除法,将计算得到的余数返回,我们都知道余数不可能大于除数,所以我们可以保证求余计算得到的结果一定比除数小,从而可以达到我们的随机数的要求,程序如下:

right_number=$[$RANDOM%$max+1]	# 随机生成一个符合范围的随机值

    下面,我们需要就用户输入的数据进行比较,得出大小关系,先判断相等的情况,这里要返回成功信息,再判断不相等的两个情况,使用的if语句的三重判断,程序如下:

if [ $right_number -eq $guess_number ];then
   # 回答正确
elif [ $right_number -lt $guess_number  ];then
  echo 'you guess too big'   # 猜的数比正确的大
elif [ $right_number -gt $guess_number  ];then
  echo 'you guess too small'  # 猜的数比正确的校 
else
  # 软件判断异常处理,逻辑上不会发生
  echo 'sorry yzy is sleeping , you can guess later'
fi

    可以完成生成和一次的判断后,我们就要来对程序进行循环部署,因为一次猜对的概率很小,尤其是范围大的时候,所以我们就要做一个循环,直到用户答对才能退出循环,换言之,我们要做一个死循环,而死循环的唯一出口是用户答对(直接结束进程这种粗暴的手段,不适合我们文明人,就不算哈),用while语句写出有个死循环,里面循环执行用户输入,判断数据,而在判断数据的回答正确一块,设置退出exit命令,程序如下:

while :
do
read -p 'please tell yzy what you guess : ' guess_number  # 用户输入猜测的数
if [ $right_number -eq $guess_number ];then
   # 回答正确的一些操作
   exit
elif ……
fi
done

二、输入合法判断

    因为需要用户参与,所以,用户输入符合不符合规定就很重要,如何判断用户输入的是不是数字,而输入的数字是否符合范围,那么我们就需要进行判断,并且对异常情况要有处理,如何处理呢,首先我想的是正则表达式,后来发现,判断之后还要再判断数是否在范围内,正则判断数据是否都是数字的代码是:

# if [ [ $guess_number=~^[0-9]+$ ] ]

    后来我从网上发现了一个很巧妙的方法,原理就是通过执行强型判断数据和1以及最大值的大小关系,如果输入数据不是全数字,系统会报错,我们只要用if语句直接判断,如果数据不是数字,系统报错,并且执行else语句,如果数据是纯数字,但是不在范围里,也会执行else,这样一举两得,唯一的问题就是,用户不能看到报错信息呀,这怎么办呢,很简单,把判断的所有输出全部丢去/dev/null,这个文件可以被重定向,并且不因数据多少占用内存,代码如下:

if [ $guess_number -gt 0 ] &>/dev/null && [ $guess_number -le $max ] &>/dev/null ;then
  number=$[$number+1]
   # 输入合法并且在范围内 , 进行判断大小等操作
else
  # 输入不合法或者不在范围内
  echo "sorry you just can guess a number from 0 to $max"
fi

三、输入猜测数据的范围

    为了提高程序的可用性,我们设置了输入的功能,用户可以设置程序的范围,可是,如果用户没有输入,我们也要有个默认值,这个很简单,有个语句可以完成这个功能,不过,如果没学过,可以用判断语句来做,代码如下:

# 判断是否有输入猜测的最大值(默认是100)
max=${1:-100}
# if [ $# -eq 0 ];then  判断检查并赋予默认值
#   max=100
# else
#   max=$1
# fi

四、程序计时和计算猜测次数

    计时,这个说简单不简单,说难不难,shell脚本中有办法直接获取当前时间,然后可以做加减计算,所以,我们在开始程序的时候记录一个数据,等结束的时候记录一个数据,相减就好了,但是这算出来的是秒数,如果耗时较长,几万秒什么的,记录和用户体验都不好,所以,我们就要把时间进行换算,而这就比较复杂,代码如下:

# 记录脚本开始时间
start_time=$(date +%s)

# 运行脚本

# 结束的时候
end_time=$(date +%s)		# 存储终止时间
second=$[$end_time-$start_time]	# 存储消耗时间的秒数
if [ $second -gt 60 ];then
  min=$[$second/60]		    # 存储消耗时间的分钟数
  all_time="${min}m"		# 存储消耗时间的综合字符串数据
  if [ $min -gt 60 ];then
    hour=$[$min/60]		    # 存储消耗时间的小时数
    min=$[$min%60]
    all_time="${hour}h ${min}m"
  fi
  second=$[$second%60]
  all_time="${all_time} ${second}s"
else
  all_time="${second}s"
fi
  echo "you all use $all_time"

    计算猜测次数就比较简单了,只需要在循环前初始化设置有个变量,在用户没输入有个数据并且判定合法有效后就+1就好了,代码如下:

number=0			# 记忆猜测次数
# 开始无限循环,直到回答正确才能跳出
while :
do
read -p 'please tell yzy what you guess : ' guess_number
# 判断输入是否符合规范
if [ $guess_number -gt 0 ] &>/dev/null && [ $guess_number -le $max ] &>/dev/null ;then
  number=$[$number+1]    # 次数+1
………………
fi
done

五、日志文件 

    为了记录猜测的历史消息,我们设立有个日志文件,用来记录什么时间谁猜了几次用了多少时间,不过,既然是日志文件,那至少有这个文件,所以我们要创建这个文件,但是,如果他存在,说明他里面有数据,我们就不能创建,这时候,我们就要判断文件是否存在,代码:

if [ ! -f /opt/guess.log ];then
  touch /opt/guess.log
fi

# 运行程序

 # 将猜测的历史记录记录到日志文件中,(日期 猜测用户 消耗时间)
echo "$(date +%Y-%m-%d) $(date +%H:%M:%S)   $USER guess $number times and use $all_time" >> /opt/guess.log

六、程序

    讲了这么多,给大家看看程序的全貌吧:

#!/bin/bash

# 记录脚本开始时间
start_time=$(date +%s)

# 判断日志文件是否存在
if [ ! -f guess.log ];then
  touch guess.log
fi
# 判断是否有输入猜测的最大值(默认是100)
max=${1:-100}
# if [ $# -eq 0 ];then  判断检查并赋予默认值
#   max=100
# else
#   max=$1
# fi

echo "welcome to yzy guess number from 1 to $max"
right_number=$[$RANDOM%$max+1]	# 随机生成一个符合范围的随机值
number=0			# 记忆猜测次数
# 开始无限循环,直到回答正确才能跳出
while :
do
read -p 'please tell yzy what you guess : ' guess_number
# 判断输入是否符合规范
# if [ [ $guess_number=~^[0-9]+$ ] ]   正则处理方法
if [ $guess_number -gt 0 ] &>/dev/null && [ $guess_number -le $max ] &>/dev/null ;then
  number=$[$number+1]
  # 猜对了
  if [ $right_number -eq $guess_number ];then
    echo 'you are right'
    echo you just guess $number times
    # 将计算所用时间
    end_time=$(date +%s)		# 存储终止时间
    second=$[$end_time-$start_time]	# 存储消耗时间的秒数
    if [ $second -gt 60 ];then
       min=$[$second/60]		# 存储消耗时间的分钟数
       all_time="${min}m"		# 存储消耗时间的综合字符串数据
       if [ $min -gt 60 ];then
          hour=$[$min/60]		# 存储消耗时间的小时数
          min=$[$min%60]
          all_time="${hour}h ${min}m"
       fi
       second=$[$second%60]
       all_time="${all_time} ${second}s"
    else
       all_time="${second}s"
    fi
    echo "you all use $all_time"
    # 根据上限和猜测次数,对这次猜测的评分
    if [ $number -eq 1 ];then
      echo  'legendary !'
    elif [ $number -lt $[$max/25] ];then
      echo  'godlike !'
    elif [ $number -lt $[$max/10] ];then
      echo 'good guy '
    else 
      echo 'so low'
    fi
    # 将猜测的历史记录记录到日志文件中,(日期 猜测用户 消耗时间)
    echo "$(date +%Y-%m-%d) $(date +%H:%M:%S)   $USER guess $number times and use $all_time" >> guess.log    
    # 回答正确退出程序
    exit
  # 猜错了,告知猜测的大小关系
  elif [ $right_number -lt $guess_number  ];then
    echo 'you guess too big'
  elif [ $right_number -gt $guess_number  ];then
    echo 'you guess too small'
  # 软件判断异常处理,逻辑上不会发生
  else
    echo 'sorry yzy is sleeping , you can guess later'
  fi
# 非法输入处理
else
  echo "sorry you just can guess a number from 0 to $max"
fi
done

PS:新手撰写,可能有些问题,欢迎大家指出,本脚本是笔者自己所写,可以转载请注明出处,谢谢。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值