1. 程式人生 > >SHELL腳本進階練習題

SHELL腳本進階練習題

管理 rip echo case parameter linu netmask 當即吃了一半 art

用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 "[email protected]*([0-9]+)\..*@\[email protected]" /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

SHELL腳本進階練習題