设为首页 收藏本站
查看: 803|回复: 0

Linux-Shell脚本编程进阶

[复制链接]

尚未签到

发表于 2018-8-18 06:25:20 | 显示全部楼层 |阅读模式
   DSC0000.jpg
  本章内容
  条件判断
  循环
  信号捕捉
  函数
  数组
  高级字符串操作
  高级变量
  Expect
  流程控制
  过程式编程语言:
  顺序执行
  选择执行
  循环执行
  条件选择if语句
  选择执行:
  注意:if语句可嵌套
  单分支
  if 判断条件;then
  条件为真的分支代码
  fi
  双分支
  if 判断条件; then
  条件为真的分支代码
  else
  条件为假的分支代码
  fi
  if 语句
  多分支
  if 判断条件1; then
  条件为真的分支代码
  elif 判断条件2; then
  条件为真的分支代码
  elif 判断条件3; then
  条件为真的分支代码
  else
  以上条件都为假的分支代码
  fi
  逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
  If示例
  根据命令的退出状态来执行命令
  if ping -c1 -W2 station1 &> /dev/null; then
  echo 'Station1 is UP'
  elif grep "station1" ~/maintenance.txt &> /dev/null
  then
  echo 'Station1 is undergoing maintenance‘
  else echo 'Station1 is unexpectedly DOWN!' exit 1
  fi
  条件判断:case语句
  case 变量引用 in
  PAT1)
  分支1
  ;;
  PAT2)
  分支2
  ;;
  ...
  *)
  默认分支
  ;;
  esac
  case支持glob风格的通配符:
  *: 任意长度任意字符
  ?: 任意单个字符
  []:指定范围内的任意单个字符
  a|b: a或b
  练习
  1、编写脚本/root/bin/createuser.sh,实现如下功能:使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id号等信息
  答:
  #!/bin/bash
  #FileName:  createuser.sh
  [ $# -ne 1 ] && echo "1 user" && exit
  useradd $1 &> /dev/null
  if [ $? -ne 0 ];then
  echo "user $1 existed"
  else
  echo "user $1 added successfully"
  getent passwd $1
  fi
  执行结果如下:
  [root@centos7 bin]#./createuser.sh user1
  user user1 added successfully
  user1:x:1021:1022::/home/user1:/bin/bash
  [root@centos7 bin]#./createuser.sh user1
  user user1 existed
  2、编写脚本/root/bin/yesorno.sh,提示用户输入yes或no,并判断用户输入的是yes还是no,或是其它信息
  答:
  #!/bin/bash
  #FileName:  yesorno.sh
  read -p "Do you agree? yes or no: " ANS
  if [[ $ANS =~ ^([Yy]([Ee][Ss])?)$ ]];then
  echo "your name is yes"
  elif [[ $ANS =~ ^([Nn][Oo]?)$ ]]:then
  echo "your answer is no"
  else
  echo "Please input yes or no"
  fi
  执行结果如下
  [root@centos7 bin]#./yesorno.sh
  Do you agree? yes or no: y
  your name is yes
  [root@centos7 bin]#./yesorno.sh
  Do you agree? yes or no: n
  your answer is no
  [root@centos7 bin]#./yesorno.sh
  Do you agree? yes or no: a
  Please input yes or no
  3、编写脚本/root/bin/filetype.sh,判断用户输入文件路径,显示其文件类型(普通,目录,链接,其它文件类型)
  答:
  #!/bin/bash
  #FileName:  filetype.sh
  read -p "Please input a filepath: " path
  ls -ld $path &> /dev/null
  if [ $? -ne 0 ];then
  echo "The file is not existed"
  else
  type=`ls -ld $path | head -c1`
  fi
  case $type in
  -)
  echo "$path is a regular file"
  ;;
  d)
  echo "$path is a directory"
  ;;
  b)
  echo "$path is a block device file"
  ;;
  c)
  echo "$path is a character device file"
  ;;
  l)
  echo "$path is a symbolic link"
  ;;
  p)
  echo "$path is a named pipe"
  ;;
  s)
  echo "$path is a local socket file"
  ;;
  *)
  echo "error"
  esac
  执行结果如下:
  [root@centos7 bin]#./filetype.sh
  Please input a filepath: /etc/fstab
  /etc/fstab is a regular file
  [root@centos7 bin]#./filetype.sh
  Please input a filepath: /root
  /root is a directory
  [root@centos7 bin]#./filetype.sh
  Please input a filepath: /dev/sda
  /dev/sda is a block device file
  [root@centos7 bin]#./filetype.sh
  Please input a filepath: /dev/zero
  /dev/zero is a character device file
  [root@centos7 bin]#./filetype.sh
  Please input a filepath: /bin
  /bin is a symbolic link
  4、编写脚本/root/bin/checkint.sh,判断用户输入的参数是否为正整数
  #!/bin/bash
  #FileName:  checkint.sh
  read -p "Please input a positive integer: " INT
  if [[ $INT =~ ^[0-9]+$ ]];then
  echo "\"$INT\" is a positive integer"
  else
  echo "\"$INT\" is not a positive integer"
  fi
  执行结果如下:
  [root@centos7 bin]#./checkint.sh
  Please input a positive integer: 23
  "23" is a positive integer
  [root@centos7 bin]#./checkint.sh
  Please input a positive integer: -16
  "-16" is not a positive integer
  [root@centos7 bin]#./checkint.sh
  Please input a positive integer: abc
  "abc" is not a positive integer
  循环
  循环执行
  将某代码段重复运行多次
  重复运行多少次
  循环次数事先已知
  循环次数事先未知
  有进入条件和退出条件
  for, while, until
  for循环
  for 变量名 in 列表;do
  循环体
  done
  执行机制:
  依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束
  列表生成方式:
  (1) 直接给出列表
  (2) 整数列表:
  (a) {start..end}
  (b) $(seq [start [step]] end)
  (3) 返回列表的命令
  $(COMMAND)
  (4) 使用glob,如:*.sh
  (5) 变量引用;
  $@, $*
  例:for file in `ls /boot`; do echo The filename is $file; done
  练习:for实现
  1、判断/var/目录下所有文件的类型
  #!/bin/bash
  #FileName:  filetype_var.sh
  for path in `ls -d /var/*`;do
  type=`ls -ld $path | head -c1`
  case $type in
  -)
  echo "$path is a regular file"
  ;;
  d)
  echo "$path is a directory"
  ;;
  b)
  echo "$path is a block device file"
  ;;
  c)
  echo "$path is a character device file"
  ;;
  l)
  echo "$path is a symbolic link"
  ;;
  p)
  echo "$path is a named pipe"
  ;;
  s)
  echo "$path is a local socket file"
  ;;
  *)
  echo "error"
  ;;
  esac
  done
  执行结果如下:
  [root@centos7 bin]#./filetype_var.sh
  /var/account is a directory
  /var/adm is a directory
  /var/cache is a directory
  /var/crash is a directory
  /var/db is a directory
  /var/empty is a directory
  /var/games is a directory
  /var/gopher is a directory
  /var/kerberos is a directory
  /var/lib is a directory
  /var/local is a directory
  /var/lock is a symbolic link
  /var/log is a directory
  /var/mail is a symbolic link
  /var/nis is a directory
  /var/opt is a directory
  /var/preserve is a directory
  /var/run is a symbolic link
  /var/spool is a directory
  /var/target is a directory
  /var/tmp is a directory
  /var/www is a directory
  /var/yp is a directory
  2、添加10个用户user1-user10,密码为8位随机字符
  #!/bin/bash
  #FileName:  createusers.sh
  for num in {1..10};do
  useradd user$num &> /dev/null
  if [ $? = 0 ];then
  echo user$num created successfully
  echo `openssl rand -base64 6` | passwd --stdin user$num &> /dev/null
  else
  echo user$num existed
  fi
  done
  执行结果如下:
  [root@centos7 bin]#./createusers.sh
  user1 created successfully
  user2 created successfully
  user3 created successfully
  user4 created successfully
  user5 created successfully
  user6 created successfully
  user7 created successfully
  user8 created successfully
  user9 created successfully
  user10 created successfully
  3、/etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的文件;分别读取每个文件,以K开头的输出为文件加stop,以S开头的输出为文件名加start,如K34filename stop S66filename start
  #!/bin/bash
  #FileName:  rc3.d_KS.sh
  for i in `ls /etc/rc.d/rc3.d`;do
  if [[ $i =~ ^K.*$ ]];then
  echo $i stop;
  elif [[ $i =~ ^S.*$ ]];then
  echo $i start;
  else
  :
  fi
  done
  [root@centos7 bin]#./rc3.d_KS.sh
  K50netconsole stop
  S10network start
  4、编写脚本,提示输入正整数n的值,计算1+2+…+n的总和
  #!/bin/bash
  #FileName:  sum_n.sh
  while true; do
  read -p "Please input a positive integer: " n
  [[ $n =~ ^[1-9][0-9]*$ ]] && break
  done
  sum=0
  for i in `seq 1 $n`;do
  sum=$[sum+i]
  done
  echo "n=$n"
  echo "1+2+...+$n=$sum"
  执行结果如下:
  [root@centos7 bin]#./sum_n.sh
  Please input a positive integer: 100
  n=100
  1+2+...+100=5050
  5、计算100以内所有能被3整除的整数之和
  #!/bin/bash
  #FileName:  sum_%3=0.sh
  sum=0
  for i in {0..100};do
  if [ $[i%3] -eq 0 ];then
  sum=$[sum+i]
  else
  :
  fi
  done
  echo sum=$sum
  执行结果如下:
  [root@centos7 bin]#./sum_%3\=0.sh
  sum=1683
  6、编写脚本,提示请输入网络地址,如192.168.0.0,判断输入的网段中主机在线状态
  #!/bin/bash
  #FileName:  scanip.sh
  # 提示输入网络地址,用正则表达式判断网段合法性
  while true; do
  read -p "Please input an ip net, such as 192.168.0.0, the script will scan ip net 192.168.0.0/24: " address
  if [[ $address =~ ^(([1-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$ ]];then
  echo -e "ip is legal, start scanning...\n"
  break
  else
  echo -e "wrong ip address\n"
  fi
  done
  # 开始扫描
  net=`echo $address | sed -r 's/^(.*)\..*$/\1/'`
  for i in {1..254};do {
  if ping -c1 -w1 $net.$i &> /dev/null ;then
  echo "$net.$i is up"
  else
  echo "$net.$i is down"
  fi } &
  done
  wait
  执行结果如下:
  [root@centos7 bin]#./scanip.sh
  Please input an ip net, such as 192.168.0.0, the script will scan ip net 192.168.0.0/24: 192.168.0.0
  ip is legal, start scanning...
  192.168.0.1 is up
  192.168.0.103 is up
  192.168.0.104 is up
  192.168.0.113 is up
  192.168.0.114 is up
  192.168.0.5 is down
  192.168.0.2 is down
  ……
  ……
  192.168.0.177 is down
  192.168.0.245 is down
  192.168.0.232 is down
  192.168.0.228 is down
  7、打印九九乘法表
  #!/bin/bash
  #Filename:  9×9.sh
  for i in {1..9};do
  for j in `seq 1 $i`;do
  result=$[j*i]
  echo -e "${j}×${i}=$result\t\c"
  done
  echo
  done
  执行结果如下:
DSC0001.jpg

  8、在/testdir目录下创建10个html文件,文件名格式为数字N(从1到10)加随机8个字母,如:1AbCdeFgH.html
  #!/bin/bash
  #Filename:  touch_Nrand.html.sh
  mkdir /testdir/ &> /dev/null
  rand=0
  for i in {1..10};do
  rand=`openssl rand -base64 20 | tr -dc [[:alpha:]] | head -c8`
  touch "/testdir/$i$rand.html"
  done
  执行结果如下:
  [root@centos7 bin]#./touch_Nrand.html.sh
  [root@centos7 bin]#cd /testdir
  [root@centos7 testdir]#ls
  10InrYzLKS.html  3rlecXfCR.html  6MjgPCXtX.html  9qQGRIxir.html
  1maGPaaSn.html   4LZssBMjM.html  7ImLLSRih.html
  2vjaOmtIO.html   5goBpJYRs.html  8OXhFdlTZ.html
  9、打印等腰三角形
  #!/bin/bash
  #Filename:  triangle.sh
  while true;do
  read -p "Please input the high of the triangle: " high
  [[ $high =~ ^[0-9]+$ ]] && break
  done
  for i in `seq $high`;do
  for j in `seq $[high-i]`;do echo -e " \c";done
  for k in `seq $[2*i-1]`;do echo -e "*\c";done
  echo
  done
  执行结果如下:
DSC0002.jpg

  while循环
  while CONDITION; do
  循环体
  done
  CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环
  因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正
  进入条件:CONDITION为true
  退出条件:CONDITION为false
  练习:用while实现
  1、编写脚本,求100以内所有正奇数之和
  #!/bin/bash
  #FileName:  while_sum.sh
  i=0
  sum=0
  while [ $i -le 100 ] ;do
  if [ $[i%2] -eq 1 ];then
  sum=$[sum+i]
  fi
  let i++
  done
  echo sum=$sum
  执行结果如下:
  [root@centos7 bin]#./while_sum.sh
  sum=2500
  2、编写脚本,提示请输入网络地址,如192.168.0.0,判断输入的网段中主机在线状态,并统计在线和离线主机各多少
  #!/bin/bash
  #FileName:  scanup.sh
  # 提示输入网络地址,用正则表达式判断网段合法性
  while true; do
  read -p "Please input an ip net, such as 192.168.0.0, the script will scan
  ip net 192.168.0.0/24: " address
  if [[ $address =~ ^(([1-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([1-
  9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$ ]];then
  echo -e "ip is legal, start scanning...\n"
  break
  else
  echo -e "wrong ip address\n"
  fi
  done
  # 开始扫描
  net=`echo $address | sed -r 's/^(.*)\..*$/\1/'`
  i=1
  touch ./scanup_tmp
  while [ $i -le 254 ];do {
  if ping -c1 -w1 $net.$i &> /dev/null ;then
  echo "$net.$i is up" | tee -a ./scanup_tmp
  else
  echo "$net.$i is down" | tee -a ./scanup_tmp
  fi } &
  let i++
  done
  wait
  up=`grep up ./scanup_tmp | wc -l`
  down=`grep down ./scanup_tmp | wc -l`
  rm -f ./scanup_tmp &> /dev/null
  echo
  echo up=$up
  echo down=$down
  # 扫描结束
  执行结果如下:
  [root@centos7 bin]#./scanup.sh
  Please input an ip net, such as 192.168.0.0, the script will scan ip net 192.168.0.0/24: 192.168.0.0
  ip is legal, start scanning...
  192.168.0.1 is up
  192.168.0.104 is up
  192.168.0.103 is up
  192.168.0.5 is down
  ……
  192.168.0.243 is down
  192.168.0.251 is down
  192.168.0.247 is down
  up=6
  down=248
  3、编写脚本,打印九九乘法表
  #!/bin/bash
  #FileName:  9×9_while.sh
  declare -i i=1
  while [ $i -le 9 ];do
  declare -i j=1
  while [ $j -le $i ];do
  result=$[j*i]
  echo -e "${j}×${i}=$result\t\c"
  let j++
  done
  echo
  let i++
  done
  执行结果如下:
DSC0003.jpg

  4、编写脚本,利用变量RANDOM生成10个随机数字,输出这个10数字,并显示其中的最大值和最小值
  #!/bin/bash
  #FileName:  10_random_num.sh
  declare -i rand min max i=1
  echo "10 random numbers: "
  while [ $i -le 10 ]; do
  rand=$RANDOM
  echo $i $rand
  [ $i -eq 1 ] && { min=$rand; max=$rand; }
  [ "$rand" -lt "$min" ] && min=$rand
  [ "$rand" -gt "$max" ] && max=$rand
  let i++
  done
  echo min $min
  echo max $max
  执行结果如下:
  [root@centos7 bin]#./10_random_num.sh
  10 random numbers:
  1 1309
  2 23514
  3 21965
  4 6954
  5 25446
  6 19996
  7 16356
  8 4571
  9 32208
  10 8522
  min 1309
  max 32208
  5、编写脚本,实现打印国际象棋棋盘
  #!/bin/bash
  #FileName:  chess.sh
  # 给国际象棋棋盘选2种颜色
  # 打印8种颜色
  echo "Please select 2 colour for the chessboard: "
  for i in {0..7};do
  echo -e "$[i+1]\033[1;4${i}m  \033[0m    \c"
  done
  echo -e "\n"
  # 选择颜色1
  while true;do
  read -p "Select the first colour (1-8): " C1
  [[ "$C1" =~ ^[1-8]$ ]] && break
  done
  echo -e "The first colour is $C1\033[1;4$[C1-1]m  \033[0m\n"
  # 选择颜色2
  while true;do
  read -p "Select the second colour (1-8): " C2
  [[ "$C2" =~ ^[1-8]$ ]] && break
  done
  echo -e "The second colour is $C2\033[1;4$[C2-1]m  \033[0m\n"
  # 选择棋盘大小
  while true;do

  read -p "Now select the>  [[ "$S" =~ ^[1-9]$ ]] && break
  done
  # 打印棋盘
  echo  "Print the chessboard: "
  echo
  for i in `eval echo {0..$[8*S-1]}`;do
  for j in `eval echo {0..$[8*S-1]}`;do
  if [ $[(i/S+j/S)%2] -eq 0 ];then
  echo -e "\033[1;4$[C1-1]m  \033[0m\c"
  else
  echo -e "\033[1;4$[C2-1]m  \033[0m\c"
  fi
  done
  echo
  done
  # 打印结束
  执行结果如下:
DSC0004.jpg

  6、后续六个字符串:efbaf275cd、4be9c40b8b、44b2395c46、f8c8873ce0、b902c16c8b、ad865d2f63是通过对随机数变量RANDOM随机执行命令: echo $RANDOM|md5sum|cut -c1-10 后的结果,请破解这些字符串对应的RANDOM值
  #!/bin/bash
  #FileName:  rand_md5sum.sh
  declare -i i=0
  declare md5
  while [ $i -le 32767 ]; do {
  md5=`echo $i | md5sum | cut -c1-10`
  case $md5 in
  efbaf275cd)
  echo "efbaf275cd ---> $i" | tee -a ./md5sum.txt
  ;;
  4be9c40b8b)
  echo "4be9c40b8b ---> $i" | tee -a ./md5sum.txt
  ;;
  44b2395c46)
  echo "44b2395c46 ---> $i" | tee -a ./md5sum.txt
  ;;
  f8c8873ce0)
  echo "f8c8873ce0 ---> $i" | tee -a ./md5sum.txt
  ;;
  b902c16c8b)
  echo "f8c8873ce0 ---> $i" | tee -a ./md5sum.txt
  ;;
  ad865d2f63)
  echo "f8c8873ce0 ---> $i" | tee -a ./md5sum.txt
  ;;
  *)
  ;;
  esac } &
  let i++
  done
  wait
  cat ./md5sum.tx
  脚本结束,输出结果如下:
  f8c8873ce0 ---> 1000
  f8c8873ce0 ---> 3000
  f8c8873ce0 ---> 6000
  44b2395c46 ---> 9000
  4be9c40b8b ---> 12000
  efbaf275cd ---> 15000
  until循环
  until CONDITION; do
  循环体
  done
  进入条件: CONDITION 为false
  退出条件: CONDITION 为true
  循环控制语句continue
  用于循环体中
  continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
  while CONDTIITON1; do
  CMD1
  ...
  if CONDITION2; then
  continue
  fi
  CMDn
  ...
  done
  循环控制语句break
  用于循环体中
  break [N]:提前结束第N层循环,最内层为第1层
  while CONDTIITON1; do
  CMD1
  ...
  if CONDITION2; then
  break
  fi
  CMDn
  ...
  done
  循环控制shift命令
  shift [n]
  用于将参量列表 list 左移指定次数,缺省为左移一次。
  参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到 shift
  ./doit.sh a b c d e f g h
  ./shfit.sh a b c d e f g h
  示例:doit.sh
  #!/bin/bash
  # Name: doit.sh
  # Purpose: shift through command line arguments
  # Usage: doit.sh [args]
  while [ $# -gt 0 ] # or (( $# > 0 ))
  do
  echo $*
  shift
  done
  示例:shift.sh
  #!/bin/bash
  #step through all the positional parameters
  until [ -z "$1" ]
  do
  echo "$1"
  shift
  done
  echo
  创建无限循环
  while true; do
  循环体
  done
  until false; do
  循环体
  Done
  练习
  1、每隔3秒钟到系统上获取已经登录的用户的信息;如果发现用户hacker登录,则将登录时间和主机记录于日志/var/log/login.log中,并退出脚本
  #!/bin/bash
  #FileName:  hacker_login.sh
  until false; do
  if who | grep "^hacker\ " &> /dev/null; then
  who | grep "^hacker\ " >> /var/log/login.log
  break
  fi
  sleep 3
  done
  如果想让脚本在后台运行,可输入nohup ./hacker_login.sh &> /dev/null &
  hacker用户登录后脚本退出,执行结果如下:
  [root@centos7 bin]#cat /var/log/login.log
  hacker   pts/1        2018-05-10 16:20 (192.168.30.1)
  2、随机生成10以内的数字,实现猜字游戏,提示比较大或小,相等则退出
  #!/bin/bash
  #FileName:  guess.sh
  num=$[RANDOM%11]
  while true;do
  read -p "Please guess the number between 0 and 10: " guess
  if [[ ! $guess =~ [[:digit:]]+ ]];then
  :
  elif [ $guess == $num ];then
  echo "You are right! The number is ${num}!"
  break
  elif [ $guess -gt $num ];then
  echo "too large"
  elif [ $guess -lt $num ];then
  echo "too small"
  else
  :
  fi
  done
  执行结果如下:
  [root@centos7 bin]#./guess.sh
  Please guess the number between 0 and 10: aaa
  Please guess the number between 0 and 10: 5
  too large
  Please guess the number between 0 and 10: 3
  too large
  Please guess the number between 0 and 10: 1
  You are right! The number is 1!
  3、用文件名做为参数,统计所有参数文件的总行数
  #!/bin/bash
  #FileName:  sum_line.sh
  [ $# -eq 0 ] && echo "No args" && exit
  declare sum=0
  until [ -z $1 ]; do
  if [ -e $1 ]; then
  sum=$[sum+`cat $1 | wc -l`]
  else
  echo "file '$1' is not existed"; exit
  fi
  shift
  done
  echo "There are all $sum cows."
  执行结果如下:
  [root@centos7 bin]#./sum_line.sh /etc/fstab /etc/passwd
  There are all 70 cows.
  4、用二个以上的数字为参数,显示其中的最大值和最小值
  #!/bin/bash
  #FileName:  max_and_min.sh
  [ $# -lt 2 ] && echo "at least 2 args" && exit
  min=$1
  max=$1
  until [ -z $1 ]; do
  [[ ! $1 =~ ^-?[0-9]+$ ]] && echo $1 is not a number && exit
  [ $1 -lt $min ] && min=$1
  [ $1 -gt $max ] && max=$1
  shift
  done
  echo min number is $min
  echo max number is $max
  特殊用法
  while循环的特殊用法(遍历文件的每一行):
  while read line; do
  循环体
  done < /PATH/FROM/SOMEFILE
  依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line
  练习
  扫描/etc/passwd文件每一行,如发现GECOS字段为空,则填充用户名和单位电话为62985600,并提示该用户的GECOS信息修改成功
  双小括号方法,即((…))格式,也可以用于算术运算
  双小括号方法也可以使bash Shell实现C语言风格的变量操作
  I=10
  ((I++))
  for循环的特殊格式:
  for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
  do
  循环体
  done
  控制变量初始化:仅在运行到循环代码段时执行一次
  控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断
  例:
  for (( i=1,sum=0;i  [[ $n =~ ^[1-9][0-9]?+$ ]] && break
  done
  n=$[n-1]
  # 生成并打印矩阵
  for i in `eval echo {0..$n}`; do
  for j in `eval echo {0..$n}`; do
  matrix[$i$j]=$[i*(n+1)+j+1]
  echo -e &quot;${matrix[$i$j]} \c&quot;
  done
  echo
  done
  # 开始转置矩阵
  echo -e &quot;\nswitch the matrix: \n&quot;
  declare tmp
  for i in `eval echo {1..$n}`; do
  for j in `eval echo {0..$[i-1]}`; do
  tmp=${matrix[$i$j]}
  matrix[$i$j]=${matrix[$j$i]}
  matrix[$j$i]=$tmp
  done
  done
  for i in `eval echo {0..$n}`; do
  for j in `eval echo {0..$n}`; do
  echo -e &quot;${matrix[$i$j]} \c&quot;
  done
  echo
  done
  输出结果如下:
  [root@centos7 bin]#./matrix.sh

  Please input the>  1 2 3
  4 5 6
  7 8 9
  switch the matrix:
  1 4 7
  2 5 8
  3 6 9
  字符串切片
  ${#var}:返回字符串变量var的长度
  ${var:offset}:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0 到 ${#var}-1 之间(bash4.2后,允许为负值)
  ${var:offset:number}:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分
  ${var: -length}:取字符串的最右侧几个字符
  注意:冒号后必须有一空白字符
  ${var:offset:-length}:从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容
  ${var: -length:-offset}:先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容
  注意:-length前空格
  注:这段代码有版本要求,7上有效,6上无效
  字符串处理
  基于模式取子串
  ${var#*word}:其中word可以是指定的任意字符
  功能:自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字符之间的所有字符
  ${var##*word}:同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所有内容
  示例:
  file=“var/log/messages”
  ${file#*/}: log/messages
  ${file##*/}: messages
  ${var%word*}:其中word可以是指定的任意字符
  功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一次出现word字符之间的所有字符
  file=&quot;/var/log/messages&quot;
  ${file%/*}: /var/log
  ${var%%word*}:同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符;
  示例:
  url=http://www.51cto.com:80
  ${url##*:} 80
  ${url%%:*} http
  查找替换
  ${var/pattern/substr}:查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之
  ${var//pattern/substr}: 查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之
  ${var/#pattern/substr}:查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之
  ${var/%pattern/substr}:查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之
  查找并删除
  ${var/pattern}:删除var所表示的字符串中第一次被pattern所匹配到的字符串
  ${var//pattern}:删除var所表示的字符串中所有被pattern所匹配到的字符串
  ${var/#pattern}:删除var所表示的字符串中所有以pattern为行首所匹配到的字符串
  ${var/%pattern}:删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串
  字符大小写转换
  ${var^^}:把var中的所有小写字母转换为大写
  ${var,,}:把var中的所有大写字母转换为小写
  变量赋值
  
  高级变量用法-有类型变量
  Shell变量一般是无类型的,但是bash Shell提供了declare和typeset两个命令用于指定变量的类型,两个命令是等价的
  declare [选项] 变量名
  -r 声明或显示只读变量
  -i 将变量定义为整型数
  -a 将变量定义为数组
  -A 将变量定义为关联数组
  -f 显示已定义的所有函数名及其内容
  -F 仅显示已定义的所有函数名
  -x 声明或显示环境变量和函数
  -l 声明变量为小写字母 declare -l var=UPPER
  -u 声明变量为大写字母 declare -u var=lower
  eval命令
  eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量.该命令对变量进行两次扫描
  示例:
  [root@server ~]# CMD=whoami
  [root@server ~]# echo $CMD
  whoami
  [root@server ~]# eval $CMD
  root
  [root@server ~]# n=10
  [root@server ~]# echo {0..$n}
  {0..10}
  [root@server ~]# eval echo {0..$n}
  0 1 2 3 4 5 6 7 8 9 10
  间接变量引用
  如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用
  variable1的值是variable2,而variable2又是变量名,variable2的值为value,间接变量引用是指通过variable1获得变量值value的行为
  variable1=variable2
  variable2=value
  bash Shell提供了两种格式实现间接变量引用
  eval tempvar=\$$variable1
  tempvar=${!variable1}
  示例:
  [root@server ~]# N=NAME
  [root@server ~]# NAME=q
  [root@server ~]# N1=${!N}
  [root@server ~]# echo $N1
  q
  [root@server ~]# eval N2=\$$N
  [root@server ~]# echo $N2
  q
  创建临时文件
  mktemp命令:创建并显示临时文件,可避免冲突
  mktemp [OPTION]... [TEMPLATE]
  TEMPLATE: filenameXXX
  X至少要出现三个
  OPTION:
  -d: 创建临时目录
  -p DIR或--tmpdir=DIR:指明临时文件所存放目录位置
  示例:
  mktemp /tmp/testXXX
  tmpdir=`mktemp -d /tmp/testdirXXX`
  mktemp --tmpdir=/testdir testXXXXXX
  安装复制文件
  install命令:
  install [OPTION]... [-T] SOURCE DEST 单文件
  install [OPTION]... SOURCE... DIRECTORY
  install [OPTION]... -t DIRECTORY SOURCE...
  install [OPTION]... -d DIRECTORY...创建空目录
  选项:
  -m MODE,默认755
  -o OWNER
  -g GROUP
  示例:
  install -m 700 -o wang -g admins srcfile desfile
  install -m 770 -d /testdir/installdir
  expect介绍
  expect 是由Don Libes基于Tcl( Tool Command Language )语言开发的,主要应用于自动化交互式操作的场景,借助Expect处理交互的命令,可以将交互过程如:ssh登录,ftp登录等写在一个脚本上,使之自动化完成。尤其适用于需要对多台服务器执行相同操作的环境中,可以大大提高系统管理人员的工作效率
  expect命令
  expect 语法:
  expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
  选项
  -c:从命令行执行expect脚本,默认expect是交互地执行的
  示例:expect -c 'expect &quot;\n&quot; {send &quot;pressed enter\n&quot;}'
  -d:可以输出输出调试信息
  示例:expect -d ssh.exp
  expect中相关命令
  spawn:启动新的进程
  send:用于向进程发送字符串
  expect:从进程接收字符串
  interact:允许用户交互
  exp_continue 匹配多个字符串在执行动作后加此命令
  expect
  expect最常用的语法(tcl语言:模式-动作)
  单一分支模式语法:
  expect &quot;hi&quot; {send &quot;You said hi\n&quot;}
  匹配到hi后,会输出“you said hi”,并换行
  多分支模式语法:
  expect &quot;hi&quot; { send &quot;You said hi\n&quot; } \
  &quot;hehe&quot; { send &quot;Hehe yourself\n&quot; } \
  &quot;bye&quot; { send &quot;Good bye\n&quot; }
  匹配hi,hello,bye任意字符串时,执行相应输出。等同如下:
  expect {
  &quot;hi&quot; { send &quot;You said hi\n&quot;}
  &quot;hehe&quot; { send &quot;Hehe yourself\n&quot;}
  &quot;bye&quot; { send &quot;Good bye\n&quot;}
  }
  示例
  #!/usr/bin/expect
  spawn scp /etc/fstab 192.168.8.100:/app
  expect {
  &quot;yes/no&quot; { send &quot;yes\n&quot;;exp_continue }
  &quot;password&quot; { send “111111\n&quot; }
  }
  expect eof
  示例
  #!/usr/bin/expect
  spawn ssh 192.168.8.100
  expect {
  &quot;yes/no&quot; { send &quot;yes\n&quot;;exp_continue }
  &quot;password&quot; { send “111111\n&quot; }
  }
  interact
  #expect eof
  示例:变量
  #!/usr/bin/expect
  set ip 192.168.8.100
  set user root
  set password 111111
  set timeout 10
  spawn ssh $user@$ip
  expect {
  &quot;yes/no&quot; { send &quot;yes\n&quot;;exp_continue }
  &quot;password&quot; { send &quot;$password\n&quot; }
  }
  interact
  示例:位置参数
  #!/usr/bin/expect
  set ip [lindex $argv 0]
  set user [lindex $argv 1]
  set password [lindex $argv 2]
  spawn ssh $user@$ip
  expect {
  &quot;yes/no&quot; { send &quot;yes\n&quot;;exp_continue }
  &quot;password&quot; { send &quot;$password\n&quot; }
  }
  interact
  #./ssh3.exp 192.168.8.100 root 111111
  示例:执行多个命令
  #!/usr/bin/expect
  set ip [lindex $argv 0]
  set user [lindex $argv 1]
  set password [lindex $argv 2]
  set timeout 10
  spawn ssh $user@$ip
  expect {
  &quot;yes/no&quot; { send &quot;yes\n&quot;;exp_continue }
  &quot;password&quot; { send &quot;$password\n&quot; }
  }
  expect &quot;]#&quot; { send &quot;useradd haha\n&quot; }
  expect &quot;]#&quot; { send &quot;echo 111111 |passwd --stdin haha\n&quot; }
  send &quot;exit\n&quot;
  expect eof
  #./ssh4.exp 192.168.8.100 root 111111
  示例:shell脚本调用expect
  #!/bin/bash
  ip=$1
  user=$2
  password=$3
  expect

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-553168-1-1.html 上篇帖子: Shell命令行执行SQL语句 下篇帖子: Linux的简单SHELL-YueYue
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表