SHELL脚本进阶练习题

用for实现脚本


判断/var/目录下所有文件的类型

read -p "pleasr input directory: " DIS
for F in ls $DIS;do
  TY=file $DIS/$F | egrep -o "link|text|block|directory"
  case $TY in
  text)
    echo "file $DIS/$F is file"
    ;;
  link)
    echo "file $DIS/$F is Link"
    ;;
  block)
    echo "file $DIS/$F is Block"
    ;;
  directory)
    echo "file $DIS/$F is Directory"
    ;;
  *)
    echo "file $DIS/$F is Others"
  esac;
done

添加10个用户user1-user10,密码为8位随机字符

取随机8位字符的方法
  openssl rand 4 -base64
  tr -dc '0-7' </dev/urandom |head -c8

for USER in user{1..10};do
  useradd $USER
  echo openssl rand 4 -base64 | passwd --stdin $USER &>/dev/null
  echo $USER created successful;
done

/etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的文件;分别读取每个文件,以K开头的输出为文件加stop,以S开头的输出为文件名加start,如K34filename stop S66filename start

for F in ls /etc/rc.d/rc3.d/ | egrep '^K|^S';do
  S=echo $F | egrep -o '^K|^S'
  if [ "$S" = "K" ];then
    echo $F stop
  else
    echo $F start
  fi;
done
或者
for i in ls /data/ ;do
  [[ "$i" =~ ^k. ]] && echo "$i stop"
  [[ "$i" =~ ^s.
]] && echo "$i start"
done

编写脚本,提示输入正整数n的值,计算1+2+…+n的总和

read -p 'please input digit: ' D
[ $D -gt 0 ] || echo "please input digit"
sum=0
for i in seq $D;do
  let sum+=$i;
done
echo $sum

计算100以内所有能被3整除的整数之和

sum=0
for i in {3..100..3};do
  let sum+=$i
done
echo $sum
或者
for i in {1..100};do
  if [ $[ $i%3 ] -eq 0 ];then
    let sum+=i
  fi
done
echo "sum is $sum"

编写脚本,提示请输入网络地址,如192.168.0.0,判断输入的网段中主机在线状态

read -p "please input network: " NET
SH=echo $NET | sed -rn 's/(.*\.)(.*)\.(.*)/\1/p'
for i in {0..255};do
  for j in {1..254};do
  { ping -c1 -W1 ${SH}${i}.${j} &>/dev/null && echo ${SH}${i}.${j} is up; }&
  done
  wait
done
echo "scan host is finished"

打印九九乘法表

echo "******************九九乘法表******************"
for i in {1..9};do
  for j in {1..9};do
    echo -e "$j$i=`echo $j$i | bc` \c"
    if [ $i -eq $j ];then
      echo ""
      break
    fi
  done
done

在/testdir目录下创建10个html文件,文件名格式为数字N(从1到10)加随机8个字母,如:1AbCdeFgH.html

for (( i=1;i<=10;i++ ));do
  RAN=tr -dc '[:alpha:]' &lt;/dev/urandom | head -c8
  touch /testdir/${i}${RAN}.html -p
done
echo "Ten file mkdir successful."

打印等腰三角形

read -p "please input triangle line: " line
for ((j=1;j<=$line;j++));do
COL_LOG='\e[1;5;'
COL_AND='\e[0m'
  for ((a=1;a<=line-j;a++));do
    echo -e " \c"
  done
  sum=echo 2*$j-1|bc
  for ((i=1;i<=${sum};i++));do
    RAND="$[$RANDOM%7+31]m"
    echo -e "${COL_LOG}${RAND}* \c"
  done
  echo -e "${COL_AND}"
done

猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,只剩下一个桃子了。求第一天共摘了多少?

sum=1
for ((n=1;n<10;n++));do
  sum=$[2*$[$sum+1]]
done
echo "所摘桃子数: $sum"

用while实现脚本


编写脚本,求100以内所有正奇数之和

sum=0
i=1
while [ $i -le 100 ];do
  echo -e "$i \c"
  sum=$[${sum}+${i}]
  i=$[$i+2]
done
echo
echo "100以内所有正奇数之和为:$sum"

编写脚本,提示请输入网络地址,如192.168.0.0,判断输入的网段中主机在线状态,并统计在线和离线主机各多少

read -p "please input new(eg:192.168.0.0): " net
netid=echo $net|cut -d. -f1-2
i=0
up=0
down=0
while [ $i -le 254 ];do
  j=1
  while [ $j -le 254 ];do
    if ping -c1 -w1 $netid.$i.$j &>/dev/null;then
      echo "the $netid.$i.$j is up"
      let up++
    else
      echo "the $netid.$i.$j is down"
      let down++
    fi
    let j++
  done
  let i++
done
echo "the up is $up"
echo "the down is $down"

编写脚本,打印九九乘法表

i=1
while [ "$i" -le "9" ];do
  j=1
  while [ "$j" -le "$i" ];do
    echo -e "$j$i=`echo $i$j|bc` \c"
    let j++
  done
  echo ""
  let i++
done

编写脚本,利用变量RANDOM生成10个随机数字,输出这个10数字,并显示其中的最大值和最小值

i=1
while true;do
  NUM=$RANDOM
  if [ "$i" -eq "1" ];then
    MAX=$NUM
    MIN=$NUM
  else  
    if [ "$MAX" -lt "${num[$i]}" ];then
      MAX=${num[$i]}
    elif [ "$MIN" -gt "${num[$i]}" ];then
      MIN=${num[$i]}
    else
      true
    fi
  fi
  let i++
done
echo "num is : ${num[@]}"
echo "最大值MAX:$MAX 最小值MIN:$MIN"

编写脚本,实现打印国际象棋棋盘

i=1
D_COLOR='\033[1;41m'
S_COLOR='\033[1;47m'
AND_COLOR='\033[0m'
while [ $i -le 8 ];do
  if [ "$[$i%2]" -eq "0" ];then
    j=1
    while [ $j -le 8 ];do
      if [ "$[$j%2]" -eq "0" ];then
        echo -e "${S_COLOR} ${AND_COLOR}\c"
      else
        echo -e "${D_COLOR} ${AND_COLOR}\c"
      fi
      let j++
    done
  else
    j=1
    while [ $j -le 8 ];do
      if [ "$[$j%2]" -eq "0" ];then
        echo -e "${D_COLOR} ${AND_COLOR}\c"
      else
        echo -e "${S_COLOR} ${AND_COLOR}\c"
      fi
      let j++
    done
  fi
  echo ""
  let i++
done

后续六个字符串:efbaf275cd、 4be9c40b8b、 44b2395c46、f8c8873ce0、 b902c16c8b、 ad865d2f63是通过对随机数变量RANDOM随机执行命令: echo $RANDOM|md5sum|cut –c1-10 后的结果,请破解这些字符串对应的RANDOM值

RAN=1
cat test.txt | while read CHESS;do
  { while true;do
    MD=echo $RAN|md5sum|cut -c1-10
    if [[ "$MD" == "$CHESS" ]];then
      echo $RAN
      break
    else
      let RAN++
    fi
  done }&
  wait
done

每隔3秒钟到系统上获取已经登录的⽤户的信息;如果发现⽤户hacker登录, 则将登录时间和主机记录于⽇志/var/log/login.log中,并退出脚本

until false;do
  if who |grep "^hacker>" &> /dev/null;then
    who|grep "^hacker>" > /var/log/login.log
    break
  fi
  sleep 3
done

随机⽣成10以内的数字,实现猜字游戏,提⽰⽐较⼤或⼩,相等则退出

n=$[$RANDOM%11]
time=1
while read -p "input a 0-10 number : " num ;do
  if [ $num -gt $n ];then
    echo "$num is greater"
  elif [ $num -lt $n ];then
    echo "$num is lower"
  else
    echo "guess right!"
    break
  fi
done

⽤⽂件名做为参数,统计所有参数⽂件的总⾏数

sum=0
while [ $# -gt 0 ];do
  lines=cat $1|wc -l
  shift
  sum=$[$sum+$lines]
done
echo $sum

⽤⼆个以上的数字为参数,显⽰其中的最⼤值和最⼩值

max=$1
min=$1
while [ $# -gt 0 ];do
  if [ $1 -lt $min ];then
    min=$1
  fi
  if [ $1 -gt $max ];then
    max=$1
  fi
  shift
done
echo "maxnum is $max"
echo "minnum is $min"

编写函数,实现OS的版本判断

os () {
  if [ sed -r "s@.*([0-9]+)\..*@\1@" /etc/centos-release` -eq 6 ];then
    echo "os is 6"
  else
    echo "os is 7."
  fi
}
os

编写函数,实现取出当前系统eth0的IP地址

eth0ip () {
  ip=ifconfig eth0|grep netmask|tr -s ' '|cut -d ' ' -f3
  echo ip=$ip
}
eth0ip

编写函数,实现打印绿⾊OK和红⾊FAILED

redgreen(){
  echo -e "\033[1;32mOK\033[0m"
  echo -e "\033[1;31mFAILD\033[0m"
}
redgreen

编写函数,实现判断是否⽆位置参数,如⽆参数,提⽰错误

args(){
  if [ $# -eq 0 ];then
    echo "please give a parameter!"
  fi
}
args $1

编写服务脚本/root/bin/testsrv.sh,完成如下要求

(1) 脚本可接受参数: start, stop, restart, status
(2) 如果参数非此四者之一,提示使用格式后报错退出
(3) 如是start:则创建/var/lock/subsys/SCRIPT_NAME, 并显示“启动成功” 考虑:如果事先已经启动过一次,该如何处理?
(4) 如是stop:则删除/var/lock/subsys/SCRIPT_NAME, 并显示“停止完成” 考虑:如果事先已然停止过了,该如何处理?
(5) 如是restart,则先stop, 再start 考虑:如果本来没有start,如何处理?
(6) 如是status, 则如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示“SCRIPT_NAME is running...” ,如果/var/lock/subsys/SCRIPT_NAME文件不存在,则显示“SCRIPT_NAME is stopped...”
(7)在所有模式下禁止启动该服务,可用chkconfig 和 service命令管理 说明: SCRIPT_NAME为当前脚本名

#!/bin/sh
#chkconfig:- 96 07
#description
[ -f /etc/rc.d/init.d/basename $0 ]||mv /app/script/basename $0
/etc/rc.d/init.d/basename $0&>/dev/null
chkconfig --add basename $0
start () {
  touch /var/lock/subsys/basename $0
  . /etc/init.d/functions
  action "basename $0 start successful!" true
}
stop () {
  rm /var/lock/subsys/basename $0
  . /etc/init.d/functions
  action "basename $0 is stopped" true
}
restart () {
  stop
  start
}
status () {
  if [ -f /var/lock/subsys/basename $0 ];then
    . /etc/init.d/functions
    action "basename $0 is running" true
  else
    action "basename $0 is stopped" true
  fi
}
case $1 in
start)
  if [ -f /var/lock/subsys/basename $0 ];then
    echo "basename $0 is running"
  else
    start
  fi
  ;;
stop)
  if [ -f /var/lock/subsys/basename $0 ];then
    stop
  else
    echo "basename $0 has been stopped before"
  Fi
  ;;
restart)
  if [ -f /var/lock/subsys/basename $0 ];then
    stop
    start
  else
    start
  fi
  ;;
status)
  status
  ;;
esac

编写脚本/root/bin/copycmd.sh

(1) 提示用户输入一个可执行命令名称
(2) 获取此命令所依赖到的所有库文件列表
(3) 复制命令至某目标目录(例如/mnt/sysroot)下的对应路径下
如: /bin/bash ==> /mnt/sysroot/bin/bash /usr/bin/passwd ==>/mnt/sysroot/usr/bin/passwd
(4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下: 如: /lib64/ldlinux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2
(5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命令, 并重复完成上述功能;直到用户输入quit退出

#!/bin/sh
while read -p "please input a COMMND : " command ;do
  if [[ "$command" =~ [Qq][Uu][Ii][Tt] ]];then
    break
  elif [ -z "$command" ];then
    echo "empty is not allowed."
    continue
  else
    dir=which $command 2> /dev/null
    if [ -z $dir ];then
      echo "command is not exit."
      continue
    else
      echo "command in the directory of $dir."
      ldd $dir &> /dev/null
      lib=ldd $dir |grep -Eo "/lib64/.*"|sed -r 's#(.*)\(.*\)#\1#'
    fi
  cpall(){
    mkdir -p /mnt/sysrootdirname $dir
    mkdir -p /mnt/sysroot/lib64
    cp -a $dir /mnt/sysroot$dir && echo ""$command" has been copied."
    cp -a $lib /mnt/sysroot/lib64 && echo ""$command" lib has been copied."
  }
  cpall
  fi
done

编写函数实现两个数字做为参数,返回最⼤值

#!/bin/sh
max() {
  if [ $# -ne 2 ];then
    echo "please enter two digits"
    exit 1
  else
    if [[ $1 =~ ^-?[0-9]+$ ]] && [[ $2 =~ ^-?[0-9]+$ ]];then
      if [ $1 -gt $2 ];then
        echo $1
      else
        echo $2
      fi
    else
      echo "please enter integer"
      exit 2
    fi
  fi
}
max $1 $2

斐波那契数列⼜称⻩⾦分割数列.因数学家列昂纳多·斐波那契以兔子繁殖为例 子而引入,故又称为“兔子数列”,指的是这样一个数列: 0、 1、 1、 2、 3、 5、 8、 13、 21、 34、 ……,斐波纳契数列以如下被以递归的方法定义: F(0) =0, F(1) =1, F(n) =F(n-1)+F(n-2)(n≥2) 利用函数,求n阶斐波那契数列

fibonacci(){
  if [ $1 -eq 0 ];then
    echo 0
  elif [ $1 -le 1 ];then
    echo 1
  else
    echo $[$(fibonacci $[$1-1])+$(fibonacci $[$1-2])]
  fi
}
fibonacci $1

汉诺塔(⼜称河内塔)问题是源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。 大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且 规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘,利用 函数,实现N片盘的汉诺塔的移动步骤

#!/bin/sh
step=0
move (){
  let step++
  echo "$step: move disk $1 $2 -----> $3"
}
hanoi(){
  if [ $1 -eq 1 ];then
    move $1 $2 $4
  else
    hanoi "$[$1-1]" $2 $4 $3
    move $1 $2 $4
    hanoi "$[$1-1]" $3 $2 $4
  fi
}
read -p "please input the number of plates: " number
hanoi $number A B C

输⼊若⼲个数值存⼊数组中,采⽤冒泡算法进⾏升序或降序排序

#!/bin/sh
declare -a rand
declare -i sub=
echo "Please input the numbers you want to sort:"
read -a rand
for ((i=0;i<${#rand[]}-1;i++));do
  for ((j=0;j<${#rand[
]}-i-1;j++));do
    if [ ${rand[$j]} -gt ${rand[$j+1]} ];then
      sub=${rand[$j+1]}
      rand[$j+1]=${rand[$j]}
      rand[$j]=$sub
    fi
  done
done
echo "The numbers have been sorted:${rand[*]}"

将下图所⽰,实现转置矩阵matrix.sh

1 2 3 1 4 7
4 5 6 ===> 2 5 8
7 8 9 3 6 9

#!/bin/sh
arr=([00]=1 [01]=2 [02]=3 [10]=4 [11]=5 [12]=6 [20]=7 [21]=8 [22]=9)
size=3
showmatrix () {
  for ((i=0;i<size;i++));do
    for ((j=0;j<size;j++));do
      echo -e "${arr[$i$j]} \c"
    done
    echo
  done
}
echo "Before convert"
showmatrix
for ((i=0;i<size;i++));do
  for ((j=i;j<size;j++));do
    if [ $i -ne $j ];then
      temp=${arr[$i$j]}
      arr[$i$j]=${arr[$j$i]}
      arr[$j$i]=$temp
    fi
  done
done
echo "After convert"
showmatrix

打印杨辉三⾓形

#!/bin/sh
read -p "输入高度" g #g是最高行
declare -a a
for i in seq $g;do #$i是当前行
  if [ $i -eq 1 ];then
    for o in seq $[$g-$i];do
      echo -n " "
    done
    a[1]=1
    echo "1"
    continue
  fi
  for j in seq $i;do #j表示当前行的第几个数字
    if [ $j -eq 1 ];then
      for o in seq $[$g-$i];do
        echo -n " "
      done
      echo -n "1"
      a[$i$j]=1
    elif [ $j -eq $i ];then
      echo -n " 1"
      a[$i$j]=1
    else
      let a[$i$j]=${a[$[i-1]$[j-1]]}+${a[$[i-1]$[j]]}
      echo -n " ${a[$i$j]}"
    fi
  done
  echo
done

猜你喜欢

转载自blog.51cto.com/12980155/2375578