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

Linux运维 第二阶段 (九)shell编程

[复制链接]

尚未签到

发表于 2018-8-25 09:03:46 | 显示全部楼层 |阅读模式
  Linux运维 第二阶段 (九)shell编程
  shell编程:
  一、知识点:
  1、相关概念:
  (1)脚本编程
  #bash -n  SCRIPT_FILE(判断脚本是否有语法错误)
  #bash -x  SCRIPT_FILE(判断脚本是否有语法错误,并详细列出执行的每一个步骤)
  #basename /root/sum.sh(strip directory and suffix from filenames直接取路径的基名(文件名),脚本中常用#basename  $0)
  编译器、解释器
  (2)编程语言:机器语言、汇编语言、高级语言
  静态语言:编译型语言、强类型(变量在使用前必须事先说明,甚至还需初始化)、执行前先编译,要事先转换好,如:C、C++、JAVA、C#;
  动态语言:解释型语言、弱类型(变量用时声明,甚至不区分类型)、边解释边执行(ON THE FLY),如:ASP、PHP、SHELL、PYTHON、PERL;
  面向过程:LINUX的内核是面向过程的C语言,SHELL脚本;
  面向对象:JAVA、PYTHON;
  注:PERL、C++既面向过程,也面向对象;
  (3)生成随机数:#echo  $RANDOM,bash内部自动维护的,生成数在0-32768之间;随机数生成器:/dev/random,/dev/urandom,默认都到熵池中去取随机数,若被取空,ramdom会停下来等待生成更多的随机数,所以会阻塞用户,urandom会用软件自动生成。
  2、变量:内存空间(编址的存储单元);
  十进制数10:字符型存:16bit;数值型存:8bit;
  变量类型(事先确定数据的存储格式和长度):字符型、数值型(整型、浮点型)、布尔型(真假);
  整型:8bit,0-255,若存256则会溢出;缓冲区溢出:(精心设计的溢出——网络***);
  变量名称:只能包含字母、数字、下划线,且不能以数字开头;不能与系统中存在的环境变量重名;最好做到见名知义;
  变量赋值:VAR_NAME=VALUE
  逻辑运算:与&、或|、非!、异或^
  短路逻辑运算:知道其中一个就知道其结果,如:对于与,其中一个为假,结果就为假;对于或,其中一个真,结果就为真;
  3、bash变量类型:环境变量、本地变量(局部变量)、位置变量($1,$2,...)、特殊变量($?,$*,$#,$@);
  环境变量:作用域为当前SHELL进程及其子进程;脚本在执行时会启动一个子SHELL进程;命令行中启动的脚本会继承当前SHELL环境变量;系统自动执行的脚本(非命令行启动)就需要自我定义需要的各环境变量;#export  VAR_NAME=VALUE赋值并声明为环境变量;
  本地变量:作用域为整个BASH进程;
  局部变量:作用域为当前代码段;
  位置变量:$1,$2,$3,....引用脚本的参数;
  特殊变量:$?(上一个命令执行状态的返回值),程序执行完,可能有两类返回值(程序的执行结果、程序状态返回代码(其中0为正确执行,1-255为错误执行)),写脚本时可自定义程序退出的代码;127为命令错误,2为参数错误;$@和$*,$#(参数的个数)
  #id root  &>  /dev/null
  #echo $?
  引用变量:${VAR_NAME},花括号有时可省去,但下列情形花括号不能省,
  #animal=pig
  #echo “There are some ${animal}s.”  (注意单双引号的区别)
  撤销变量:#unset  VAR_NAME  (不是操作变量的值,就不需加$)
  查看变量:#set  (查看当前SHELL所有变量)
  #printenv (以下三个都是查看环境变量)
  #env
  #export
  4、脚本:命令的堆砌,按实际需要,结合命令流程控制机制实现的源程序
  #!/bin/bash(此句必须是文件的第一行,shabang魔数)
  #which bash
  #file /bin/ls  (ELF可执行可链接的文件格式)
  执行脚本:一、赋予可执行权限,用绝对路径执行;二、#bash  脚本文件
  条件测试类型:整数测试、字符串测试、文件测试
  条件测试的表达式:[  expression  ]、[[  expression ]]、test  expression
  整数测试:-eq,-ne,-gt,-lt,-ge,-le
  字符串测试:==,!=,-n  string(空为真),-z  string(不空为真)
  文件测试:-e,-f,-d,-r,-w,-x
  #bash -n  script.sh  (测试脚本是否有语法错误)
  #bash -x  script.sh  (测试脚本是否有语法错误,每一步执行都显示出来)
  命令间的逻辑关系:逻辑与&&、逻辑或||;
  &&:前一个语句假后一个语句不执行,前一个语句真后一个语句执行;
  ||:前一个语句假后一个语句执行,前一个语句真后一个语句不执行;
  举例:
  #! id  user1  && useradd  user1  || echo  “user1  exists!”
  #! id  user1  && useradd  user1  && echo  “user1”  | passwd  --stdin  user1 ||  echo  “user1 exists”
  组合测试条件:
  -a(与关系)
  -o(或关系)
  !(非关系-not)
  举例:[  !  \( $1  ==  ‘q’  -o  $1 ==  ‘quit’  -o $1  ==  ‘Q’ \)  ]
  算术运算:
  #A=3
  #B=6
  #let c=$A+$B  (第一种方式,#help  let)
  #d=$[$A+$B]  (第二种方式)
  #e=$(($A+$B))  (第三种方式)
  #f=`expr $A  +  $B`  (第四种方式,expr算术运算表达式,表达式中各操作数及运算符之间要有空格,而且要使用命令引用,#g=$(expr  $A  +  $B)
  注:shell默认所有类型均为字符串,不能做算术运算。
  常用的赋值表达式:
  i+=1(类似于i++;i-=1(i--);i*=1;i/=1;i%=1)
  ++i;--i
  5、脚本编程知识点:
  (1)顺序结构(按行依次写命令即可,若一行执行多个语句用分号分隔)
  (2)选择结构:if单分支、双分支、多分支;case语句
  (3)循环结构:for;while;until
  (4)函数
  (5)截取路径:#man  bash
  ${parameter#*word}从左至右截取;
  ${parameter##*word};
  ${parameter%*word}从右至左截取;
  ${parameter%%*word};
  例如1:#FILE=’/usr/local/src’
  #echo ${FILE#*/}结果为/usr/local/src
  #echo ${FILE##*/}结果为src
  #echo ${FILE%/*}结果为/usr/local,此项常用,用于自动复制命令及命令的库文件的脚本
  #echo ${FILE%%/*}结果为空
  例如2:#A=`stty  -F  /dev/console size`显示屏幕大小
  #echo ${A#*  }
  #echo ${A%  *}
  (6)#echo  ${#VARNAME}列出变量所包含的的字符串长度
  例如:#echo  ${#FILE}结果为14
  (7)变量赋值:
  ${parameter:-word}如果parameter为空或未定义,则变量展开为word;否则展开为parameter的值;
  ${parameter:+word}如果parameter为空或未定义,不做任何操作;否则展开为word值;
  ${parameter:=word}如果parameter为空或未定义,则变量展开为word;并将展开的值赋给parameter;
  ${parameter:offset}
  ${parameter:offset:length}取子串,从offset处的后一个字符开始,取length长度的子串。
  例如:#echo  ${A:-30}(A为空,则展开为30)常用
  #echo ${A:+30}(A为空则空,此项可用来判断A是否有数据)
  #echo ${A:=30}(A为空,30赋值给A)
  #A=’hello world’
  #echo ${A:2}(显示结果为llo  world)
  #echo ${A:2:3}(显示结果为llo)
  (8)/etc/rc.d/init.d/服务脚本
  /etc/sysconfig/服务脚本同名的配置文件
  (9)局部变量:
  local VARNAME=VALUE
  比较有local和无local的差别,变量的作用域之间是如何影响的,例如:
  #!/bin/bash
  #
  a=1
  test() {
  local a=$[3+4]  #有local仅在当前函数中生效
  }
  test
  (10)#mktemp  FILE|DIR(创建临时文件或目录,脚本中防止创建的文件重名,可用X代替随机数的个数)
  例如:#mktemp  /tmp/file.XXXX(X为随机数的个数)
  #mktemp -d  /tmp/dir.XXXXX(-d创建目录)
  #FILE=`mktemp  /tmp/file.XXXXXXX`
  #eecho $FILE
  (11)信号:
  #kill -l(Print a list of signal names)
  常用信号:
  -SIGHUP(hangup,1)
  -SIGINT(interrupt,2,ctrl+c,中断前台正在运行的进程)
  -SIGKILL(9)
  -SIGTERM(termination,15)
  -SIGCONT(continue,18,#bg  %JOBID,将后台停止的作业让其继续运行)
  -SIGSTOP(19,ctrl+z将前台作业放至后台运行)
  脚本中可实现信号捕捉,但9和15信号无法捕捉。
  #trap ‘command’  SIGNAL
  例如:
  #!/bin/bash
  #
  trap ‘echo “you go…”’  INT
  while :;do
  date
  sleep 2
  done
  (12)数组array(连续的内存空间,元素element(数据中每一个独立的变量),每一个元素用index标示)
  #declare -a  AA(声明一个数组)
  数组赋值方法一:
  #declare -a  AA
  #AA[0]=jerry
  #AA[1]=tom
  #AA[2]=wendy
  #AA[6]=natasha
  #AA[4]=”nikita black”(值中包含空格要用引号)
  数组赋值方法二:
  #declare -a  AA
  #AA=(jerry tom  wendy)
  #AA=([0]=jerry  [1]=tom [2]=wendy  [6]=natasha  [7]=”nikita black”)
  #echo ${AA[0]}(查看数组中某元素的值)
  #echo ${AA[2]}
  #echo ${#AA[6]}(查看数组中某元素的值的字符个数)
  #echo ${AA
  • }(查看数组中所有元素的值)
      #echo ${#AA
  • }(查看数组中值不为空的元素的个数)
      #echo ${#AA[@]}(查看数组中值不为空的元素的个数)
      (13)脚本中使用选项(getopts,获取bash 脚本的选项及选项后的参数,并在脚本中调用,格式如下)
      #man getopts
      #help getopts
      getopts optstring  name  [arguments]
      注:optstring表示可用的选项都有哪些,仅支持短选项,默认只获取一个选项
      $OPTARG、$OPTIND(这是getopts内置的两个变量,$OPTARG表示选项后参数的值;$OPTIND表示选项的索引index,永远指向下一个,如有一个选项时该值是2,有两个选项时该值是3)
      shift $[$OPTIND-1](表示踢走前面的选项)
      getopts “b:d:”  OPT(b和d后的冒号表示选项后必须要跟参数,否则会报错)
      getopts “:b:d:”  OPT(第一个冒号表示不输出错误信息,这个错误信息是getopts的错误信息而不是脚本)
      使用方法:
      while getopts  “:d:”  OPT;do
      case  $OPT  in
      d)
      echo  “the option is d”
      echo  $OPTARG
      ;;
      *)
      echo  “Usage: ……”
      ;;
      esac
      done
      具体用法见以下(举例21和22)
      (2)条件判断,控制结构:
      单分支if语句:
      if  判断条件;then
      statement1
      statement2
      ......
      fi
      双分支if语句:
      if  判断条件;then
      statement1
      statement2
      ......
      else
      statement3
      statement4
      ......
      fi
      多分支if语句:
      if  判断条件1;then
      statement1
      ......
      elif 判断条件2;then
      statement2
      ......
      elif 判断条件3;then
      statement3
      ......
      else
      statement4
      ......
      fi
      case 变量  in
      value1)
      statement
      ;;
      value2)
      statement
      ;;
      *)
      statement
      ;;
      esac
      (3)循环:进入条件,退出条件,for,while,until
      for  变量  in  列表;do
      循环体
      done
      生成列表的方式:{1..100};seq  [起始数 [步进数]  尾数;
      整个语句将列表遍历完成之后退出;
      for ((expr1;expr2;expr3));do
      循环体
      done
      注:此种写法近似C语言风格,其中expr1表示初始值,expr2表示退出条件,expr3表示修正变量值)
      while CONDITION;do(条件满足进入循环,条件不满足退出循环,适用于循环次数未知的场景,注意要有退出条件)
      statement
      done
      until CONDITON;do(条件不满足进入循环,条件满足退出循环)
      statement
      done
      break(提前退出循环,可用来控制死循环)
      continue(提前结束本轮循环,而进入下一轮循环)
      while特殊用法一(死循环,需break控制退出):
      while :;do
      statement
      done
      while特殊用法二:
      while read  LINE;do
      statement
      done <  /PATH/TO/SOMEFILE
      (4)函数:
      功能function,把执行的一段代码封装成一个独立的功能,并给之取个名字,需要时直接调用(调用时直接写函数名)
      结构化编程的重要思想,主要目的实现代码重用,不能独立运行,需要调用时执行,可以被多次调用;库文件.so能被多个进程调用
      定义一个函数,两种方式,函数名可以是字母数字下划线,不能数字开头:
      function FUNCNAME{
      COMMAND
      ]
      FUNCNAME() {
      COMMAND
      }
      自定义执行状态返回值:return  #(退出函数,0-255)
      exit #(退出脚本)
      二、操作:
      举例1:
      #!/bin/bash
      #使用脚本添加或删除用户
      if [  $#  -lt 1  ]; then
      echo  “Usage: adminusers ARG.”
      exit  7
      fi
      if [  $1  ==  ‘add’  ];then
      for  I  in {1..10};do

      if >  echo “user$Iexists.”
      else
      useradd  user$I
      echo  “user$I” | passwd  --stdin user$I  &> /dev/null
      echo  “Add user$I finished.”
      fi
      done
      elif  [ $1  ==  ‘del’ ];then
      for  I  in {1..10};do

      if >  userdel  -r user$I
      echo  “Delete user$I finished.”
      else
      echo  “No user$I.”
      fi
      done
      else
      echo  “Unknown  ARG.”
      exit  8
      fi
      -------------------------------------------------------------------------------------------------------------
      举例2:
      #!/bin/bash
      #打印1到100偶数和与奇数和
      declare -i  EVENSUM=0
      declare -i  ODDSUM=0
      for I  in  {1..100};do
      if  [  $[$I%2] -eq  0  ];then
      let  EVENSUM+=$I
      else
      ODDSUM+=$I
      fi
      done
      echo “Oddsum is $ODDSUM.”
      echo “Evensum is $EVENSUM.”
      -------------------------------------------------------------------------------------------------------------
      举例3:
      #!/bin/bash
      #打印1到100的和
      declare -i  SUM=0
      for ((I=1;I /dev/null;do(此句也可写为while  !  who | grep “hadoop”  &> /dev/null;do)
      echo “hadoop is not come!”
      sleep  5
      done
      echo  “hadoop is logged in.”
      -------------------------------------------------------------------------------------------------------------
      举例5:
      #!/bin/bash
      #随机生成10个数,比较最大数最小数
      declare -i MAX=0
      declare -i MIN=0
      for I in {1..10};do
      MYRANDOM=$RANDOM
      [ $I -eq 1 ] && MIN=$MYRANDOM
      if [ $I -le 9 ];then
      echo -n "$MYRANDOM,"
      else
      echo "$MYRANDOM"
      fi
      [$MYRANDOM -gt $MAX ] && MAX=$MYRANDOM
      [$MYRANDOM -lt $MIN ] && MIN=$MYRANDOM
      done
      echo $MAX,$MIN
      举例6:
      #!/bin/bash
      #将用户输入的字符转为大写,当输入q时退出
      read -p  “Input string:  “ STRING
      while [  $STRING  !=  ‘q’  ];do
      echo  $STRING  | tr  ‘a-z’  ‘A-Z’
      read  -p  “Input string again:  “ STRING
      done
      举例7:
      #!/bin/bash
      #按步骤生成yum仓库文件
      REPOFILE=/etc/yum.repos.d/$1
      if [ -e $REPOFILE ];then
      echo "$1 is exists."
      exit 3
      fi

      read -p "Repository>  until [ $REPOID == 'quit' ];do
      echo "[$REPOID]" >> $REPOFILE
      read -p "Repository Name: " REPONAME
      echo "name=$REPONAME" >> $REPOFILE
      read -p "Repository baseurl: " REPOURL
      echo "baseurl=$REPOURL" >> $REPOFILE
      echo -e "enabled=1\ngpgcheck=0" >> $REPOFILE

      read -p "Repository>  done
      echo "Bye!"
      举例8:
      #!/bin/bash
      #理解break
      declare -i SUM=0
      for I in {1..200};do
      let SUM+=$I
      if [ $SUM -gt 5000 ];then
      break
      fi
      done
      echo $I
      echo $SUM
      举例9:
      #!/bin/bash
      #理解continue
      let SUM=0
      let I=0
      while [ $I -lt 100 ];do
      let I++
      if [ $[$I%2] -eq 0 ];then
      continue
      fi
      let SUM+=$I
      done
      echo $SUM
      举例10:
      #!/bin/bash
      #while特殊用法一
      while :;do
      read -p "File path: " FILEPATH
      [$FILEPATH == 'quit' ] && break
      if [ -e $FILEPATH ];then
      echo "$FILEPATH exists."
      else
      echo "No $FILEPATH."
      fi
      done
      #!/bin/bash
      #while特殊用法二
      useradd user1
      useradd user2
      useradd user3
      useradd user4
      useradd user5
      let I=0
      while read LINE;do
      [`echo $LINE | awk -F: '{print $3}'` -gt 503 ] && continue
      [`echo $LINE | awk -F: '{print $7}'` == '/bin/bash' ] && echo $LINE |awk -F: '{print $1}' && let I++
      [$I -eq 5 ] && break
      done < /etc/passwd
      举例11:
      #!/bin/bash
      #检查一脚本是否有语法错误,若有错误按任意键(除q与Q)编辑,若无错则直接退出
      until bash -n $1 &> /dev/null;do
      read -p "Syntax error,[Q\q] to quit,other for editing: "CHOICE
      case $CHOICE in
      q|Q)
      echo "Something wrong,quiting."
      exit 5
      ;;
      *)
      vim + $1
      esac
      done
      举例12:
      #!/bin/bash
      #理解函数
      TWOSUM() {
      echo $[$1+$2]
      }
      for I in {1..10};do
      let J=$[$I+1]
      TWOSUM $J $I
      done
      echo "$J plus $I is `TWOSUM $J$I`"
      举例13:
      #!/bin/bash
      #函数应用:添加用户(存在显示failure,不存在则添加)
      ADDUSER(){
      USERNAME=$1

      if !>  useradd $USERNAME
      echo "$USERNAME" | passwd--stdin $USERNAME &> /dev/null
      return 0
      else
      return 1
      fi
      }
      for I in `seq 1 5`;do
      ADDUSER user$I
      if [ $? -eq 0 ];then
      echo "add user$I is success."
      else
      echo "add user$I failure."
      fi
      done
      举例14:
      #!/bin/bash
      #函数应用:查看指定网段是否畅通
      PING() {
      if ping -c 1 -w 1 $1 &> /dev/null;then
      return 0
      else
      return 1
      fi
      }
      for I in {150..160};do
      PING 192.168.1.$I
      if [ $? -eq 0 ];then
      echo "192.168.1.$I is up."
      else
      echo "192.168.1.$I is down."
      fi
      done
      举例15:
      #!/bin/bash
      #查看分区、内存、交换区使用情况。
      cat  $1  /dev/null;do
      read -p "syntax error:q|Q is quit,others is edit: " OPT
      case $OPT in
      q|Q)
      echo "quit."
      exit 4
      ;;
      *)
      vim + $1
      ;;
      esac
      done
      -------------------------------------------------------------------------------------------------------------
      举例21:
      #!/bin/bash
      #在上例基础上,使用选项为脚本头部添加描述信息,用法为./mkscript –d “STRING” SCRIPT_FILE
      while getopts ":d:" OPT;do
      case$OPT in
      d)
      DEC=$OPTARG
      ;;
      *)
      echo "Usage: mkscript [-d DESCRIPTION] FILE"
      ;;
      esac
      done
      shift $[$OPTIND-1]
      if ! grep "[^[:space:]]" $1&> /dev/null;then
      cat > $1  /dev/null;do
      read -p "syntax error:q|Q is quit,others is edit: " OPT
      case $OPT in
      q|Q)
      echo"quit."
      exit 4
      ;;
      *)
      vim + $1
      ;;
      esac
      done
      -------------------------------------------------------------------------------------------------------------
      举例22:
      #export PATH=$PATH:/root
      #mkscript -d  “get  interface ip”  getinterface.sh(使用上例的脚本生成此脚本文件,编辑如下)
      #!/bin/bash
      # name: getinterface.sh
      # description: get interface ip
      # version: 0.0.1
      # author: jowin
      # datetime: 2015-10-27 19:23:13
      # Usage: getinterface.sh
      USAGE() {
      echo "Usage: getinterface.sh [-i INTERFACE] [-I IP_ADDR]"
      }
      SHOWIP() {
      if !ifconfig | grep -o "^[^[:space:]]\{1,\}" | grep $1 &>/dev/null;then
      return 13;
      fi
      echo -n "${1}: "
      ifconfig $1 | grep -o "inetaddr:[0-9\.]\{1,\}" | cut -d: -f2
      }
      SHOWETHER() {
      if !ifconfig | grep -o "inet addr:[0-9\.]\{1,\}" | cut -d: -f2 | grep $1&> /dev/null;then
      return 14;
      fi
      echo-n "${1}: "
      ifconfig | grep -B 1 $1 | grep -o"^[^[:space:]]\{1,\}"
      }
      while getopts ":i:I:" OPT;do
      case$OPT in
      i)
      SHOWIP $OPTARG
      [$? -eq 13 ] && echo "wrong interface"
      ;;
      I)
      SHOWETHER $OPTARG
      [$? -eq 14 ] && echo "wrong ip"
      ;;
      *)
      USAGE
      ;;
      esac
      done
      -------------------------------------------------------------------------------------------------------------
      -------------------------------------------------------------------------------------------------------------
      以上是学习《马哥运维课程》做的笔记。
      一、1、基础正则表达式:
      *         前一个字符匹配0次或任意多次
      .         匹配除了换行符外任意一个字符
      ^         匹配行首,例:^Hello,匹配以Hello开头的行
      $         匹配行尾,例:Hello$匹配以Hello结尾的行
      []        中括号中指定的一个字符,例:[0-9]、[a-z]
      [^]       匹配中括号字符以外的任意一个字符,例:[^0-9]、[^a-z]
      \         转义符,取消特殊符号的含义
      \{n\}     表示其前面的字符恰好出现n次,例:[0-9]\{4\}、手机号[1][3-8][0-9]\{9\}
      \{n,\}    表示其前面的字符出现不小于n次,例:[0-9]\{2,\}表示2位以上的数字
      \{n,m\}   表示其前面的字符至少出现n次,最多出现m次,例:[a-z]\{6,8\}表示6到8位小写字母
      2、扩展正则表达式:#grep–E 或 egrep
      +        前一个字符匹配1次或任意多次
      ?       前一个字符出现0次或1次,例:colou?r匹配colour和color
      |        匹配两个或多个分支选择,例:was|his,匹配包含was的行,也包含his的行
      ()       匹配其整体为一个字符,即模式单元,可理解为由多个单个字符组成的大字符,例:(dog)会出现dog,dogdog,dogdogdog等;hello(world|earth),匹配hello worlda或hello earth
      注:grep、awk、sed等命令支持正则表达式;ls、find、cp支持shell通配符
      3、#grep “a*”          t.txt          (匹配任何内容
      #grep“aa*” t.txt     (匹配至少包含一个a的行
      #grep“aaa*” t.txt    (匹配至少包含二个a 的行
      #grep“s..d” t.txt    (匹配s和d之间一定有2个字符的单词
      #grep“s.*d” t.txt    (匹配s和d之间有任意个字符
      #grep“^M” t.txt      (匹配以M开头的行
      #grep“N$” t.txt      (匹配以N结尾的行
      #grep“^$” t.txt      (匹配空白行
      #grep“^….$” t.txt   (匹配四个字符的行
      #grep“[0-9]” t.txt   (匹配含数字的行
      #grep“^[a-z]” t.txt  (字母开头的行
      #grep“[^A-Z]” t.txt  (非大写字母的行
      #grep“\.$” t.txt     (以点结尾的行
      #grep“a\{3\}” t.txt  (三个连续a的行
      #grep“[0-9]\{3,\} t.txt     (至少三个数字开头的行
      #grep“[su]a\{3,\}[iI] t.txt (s或u和i或I之间至少有三个连续的a
      #grep“sa\{1,3\}i” t.txt    (s和i之间最少有1个a最多有3个a
      二、字符截取和替换命令
      1、#cut 选项 文件名
      -f列号                fields提取第几列
      -d“分隔符”          delimiter指定分隔符
      -c字符范围            通过字符范围进行字段提取,行首为0;“n-”表示从第n个字符到行尾;“n-m”表示从第n个字符到第m个字符;“-m”表示从第1个字符到第m个字符
      例:#cut –f 2s.txt
      #cut–f 2,3 s.txt
      #cut–c 8- s.txt
      #cut–d “:” –f 1,3 s.txt
      2、awk编程
      >#printf ’输出类型输出格式’  输出内容
      输出类型:
      %ns          输出字符串,n指代输出几个字符
      %ni         输出整数,n指代输出几个数字
      %m.nf       输出浮点数,m代表总数位,n是小数位。例:%8.2f表示6位整数,2位小数
      例:#printf ‘%s’$(cat s.txt)
      #printf‘%s\t%s\t%s\t%s\t \n’ $(cat s.txt)
      #printf‘%i\t%s\t%i\t%8.2f \n’ $(cat s.txt) | grep –v Name

    •   awk ‘条件1{动作1} 条件2{动作2}……’ 文件名
      动作:格式化输出,流程控制语句
      注:在awk编程中因命令语句长,输入格式时需注意:
      》多个条件{动作}可用空格分割也可用回车分割;
      》在一个动作中,如果需要执行多个命令,要用分号分割或用回车分割;
      》变量的赋值与调用都不用加$符号;
      》条件判断两个值是否相同使用==,不要和变量赋值混淆。
      例:#awk ‘{printf$2 “\t” $6 “\t” “\n” }’ s.txt    (printf输出时在输出格式的最后要加“\n”,而print则不用。
      #df–h | awk ‘{print $2 “\t” $6}’ s.txt
      #cats.txt | grep –v Name | awk ‘$6 >= 87 {print $2}’    (加入条件后,只有条件成立动作才执行
      #awk‘BEGIN {print “this is a transcript”}  {print $2 “\t” $6}’ s.txt       (awk只要检测不到完整的‘’就不会执行,所以不用加换行符;BEGIN在读取数据前仅执行一次
      #awk‘END {print “The end!”} {print $2 “\t” $3}’ s.txt
      #awk‘$2 ~ /sb/ {print $6}’ s.txt       (第二个字段包含有sb则打印第六字段
      #awk‘/sd/ {print}’ s.txt               (打印sd的成绩
      #df–h | awk ‘/sda[0-9]/ {print $1 “\t” $5}’
      #cat/etc/passwd | grep “/bin/bash” | awk ‘BEGIN{FS=”:”} {print $1 “\t” $3}’
      #cat/etc/passwd | grep “/bin/bash” | awk ‘BEGIN{FS=”:”} {print $1 “\t” $3 “\t 行号:”\
      >NR “\t 字段数: “ NF}’        (NR总数据的第几行,NF总字段数
      注:awk是列提取命令,但也要按行来读入,执行过程:
      》如有BEGIN,则先执行BEGIN定义的动作;
      》读入第一行,第一行的数据依次赋予$0,$1,$2等变量,$0代表此行的整体数据,$1代表第一个字段,$2代表第二个字段;
      》依据条件判断动作是否执行,符合执行,否则读入下一行数据,若没条件,则每行都执行动作
      》读入下一行数据,重复以下步骤。
      #awk‘NR==2 {php1=$3}
      NR==3{php2=$3}
      NR==4{PHP=$3;total=php1+php2+php3;print”total php is ” total}’ s.txt
      #awk‘NR>=2 {test=$4}
      test>90{print $2 “is a good man!”}’ s.txt
      function函数名 (参数列表){
      函数体
      }
      #awk ‘functiontest(a,b) {print a “\t” b}
      {test($2,$6)}’ s.txt
      #vipass.awk
      BEGIN‘{FS=”:”}
      {print$1 “\t” $3}
      #awk–f pass.awk /etc/passwd
      3、sed(streameditor,对文本文件和标准输入进行编辑,键盘输入、文件重定向、字符串、变量、来自管道的文本
      #sed选项 ‘动作’文件名
      -n      有此项,输出时只会显示sed处理的行
      -e      对输入数据应用多条sed命令编辑
      -f脚本文件     与#awk –f类似
      -r      支持正则表达式
      -I      直接修改源文件中数据,而不是由屏幕输出
      动作:
      a\     append追加,在当前行后添加一行或多行,每行末尾用\代表数据未完,最后一行不用
      c\     行替换,用c后面的字符串替换原数据行,多行时用\代表数据未完,最后一行除外
      i\     insert在当前行前插入一行或多行,多行时每行末尾用\代表数据未完,最后一行除外
      d      删除指定的行
      p      打印输出指定的行
      s      字符替换,格式:行范围s/旧字串/新字串/g
      行数据操作:例子:
      #sed–n ‘2p’ s.txt
      #sed‘2,4d’ s.txt
      #sed‘2a hello’ s.txt
      #sed‘2i hello \
      >world’s.txt    (行末用\代表数据未完,在第二行前插入两行数据
      #sed–n ‘2i’ hello \
      >world’s.txt    (仅显示处理的行
      #cats.txt |sed ‘2c No such person’ (将第二行替换
      #sed–i ‘2c No such a person’ s.txt(直接处理文件数据,-i谨慎使用
      字串替换:例子:
      #sed‘s/旧/新/g’ s.txt
      #sed‘3s/74/99/g’ s.txt
      #sed‘4s/^/#/g’ s.txt
      #sed–e ‘s/sb//g ; s/sd//g’ s.txt
      三、字符处理命令
      》#sort 选项 文件名
      -f      忽略大小写ignore-case(foldlower case to upper case characters)
      -b      忽略每行前面的空白部分ignoreleading blanks
      -n      以数值排序numeric-sort
      -r      反射排序reverse
      -u      排除重复行,同uniqu命令
      -t      指定分隔符,默认是制表符
      -kn[,m]    按指定的字串范围,从n字段开始,m字段结束(默认到行尾)
      例:#sort/etc/passwd
      #sort–r /etc/passwd
      #sort–t “:” –k 3,3 /etc/passwd       (只用第3字段排序
      #sort–n –t “:” –k 3,3 /etc/passwd
      》#uniq 选项 文件名    (-i 忽略大小写
      》#wc 选项 文件名      (-l,line;-w,word;-m字符数
      四、条件判断
      1、文件类型判断:
      例:#[  -e /root/sh/  ]
      #echo$?
      #[ -d /root/sh  ] && echo “yes”|| echo “no”
      2、文件权限判断:
      #[  -w s.txt  ]&& echo “yes” ||echo “no”
      3、两个文件之间进行比较:
      #[ /root/s.txt -ef  /tmp/sut.txt ] && echo “yes”|| echo "no”                         (判断是否硬链接
      4、两个整数之间比较:
      #[  23  -ge  22  ]&& echo “yes” || echo “no”
      5、字符串的判断:
      #[  -z  “$name”  ] && echo “yes” || echo “no”
      6、多重条件判断:
      #[  -n  “$aa”  -a -n  “$aa”  -gt  23] && echo “yes” || echo “no”
      五、流程控制:
      1、if条件判断:
      》单分支:
      if[  条件判断式  ];then
      程序
      fi
      或
      if[  条件判断式  ]
      then
      程序
      fi
      注:使用fi结尾,和一般语言使用大括号不同;条件判断式使用test命令判断,中括号和条件判断式之间必须有空格;then扣是符合条件之后执行的程序,then可放在[]之后用分号分隔,也可换行写入不写分号
      例:#vi  fi1.sh
      #!/bin/bash
      rate=$(df–h | grep “/dev/sda3” | awk ‘{print $5}’ | cut –d “%” –f 1)
      if[  “$rate”  -ge 80  ]
      then
      echo“Warning! /dev/sda3 is full!”
      fi
      》双分支
      if  [  条件判断式  ]
      then
      条件成立时执行的程序
      else
      条件不成立时执行的程序
      fi
      例:#vi  backmysql.sh
      #!/bin/bash
      ntpdateasia.pool.ntp.org &>/dev/null
      date=$(date+%Y%m%d)

      >  if[  -d /tmp/dbbak  ]
      then
      echo“Date: $date!” > /tmp/dbbak/dbinfo.txt
      cd/tmp/dbbak
      tar–zcf  mysql-lib-$date.tar.gz  /var/lib/mysql  dbinfo.txt &>/dev/null
      rm–rf  /tmp/dbbak/dbinfo.txt
      else
      mkdir/tmp/dbbak
      echo“Date: $date!” > /tmp/dbbak/dbinfo.txt

      echo“Date>  cd  /tmp/dbbak
      tar–zcf  mysql-lib-$date.tar/gz  /var/lib/mysql  &>/dev/null
      rm–rf /tmp/dbbak/dbinfo.txt
      fi
      例:vi  autostart.sh
      #!/bin/bash
      port=$(nmap–sT 192.168.4.210 | grep tcp | grep http| awk ‘{print $2}’)
      if  [  “$port”  ==  “open”  ]
      then
      echo“$(date) httpd is OK!” >> /tmp/autostart-acc.log
      else
      /etc/rc.d/init.d/httpdstop       &>/dev/null
      /etc/rc.d/init.d/httpdstart    &>/dev/null
      echo“$(date) restart httpd!” >> /tmp/autostart-err.log
      fi
      》多分支
      if  [  条件判断式  ]
      then
      当条件判断式1成立时,执行程序1
      elif  [  条件判断式  ]
      then
      当条件判断式2成立时,执行程序2
      ……
      else
      当所有条件都不成立时,执行此程序
      fi
      例:#vi  if-elif.sh
      #!/bin/bash
      read–p “please input a filename:  “ file
      if  [ -z  “$file”  ]
      then
      echo“Error,please input a filename.”
      elif  [  ! –e “$file” ]
      then
      echo“Your input is not a file”
      elif  [ -f  “$file”  ]
      then
      echo“$file is a regulaar file.”
      elif  [ -d  “$file”  ]
      then
      echo“$file is a directory!”
      else
      echo“$file is an other file!”
      fi
      2、多分去case条件语句:case只判断一种条件关系,而if可判断多种条件关系。
      case$变量名 in
      “值1”)
      如果变量的值等于值1,则执行程序1
      ;;
      “值2”)
      如果变量的值等于值2,则执行程序2
      ;;
      ……
      *)
      如果变量的值都不是以上的值,执行此程序
      ;;
      esac
      注:case语句会取出变量中的值,与语句体中的值逐一比较,符合则执行相应程序,不符依次比较下一个值。若所有值都不符合,则执行*)后的程序,*代表所有其它值;以case开头,esac结尾;每个分支之后要用;;结尾,代表该程序段结束。
      例:#vi case.sh
      #!/bin/bash
      read–p  “please chose yes/no: “ cho
      case$cho in
      “yes”)
      echo“Your choose is yes!”
      ;;
      “no”)
      echo“Your choose is no”
      ;;
      *)
      echo“Your choose is error!”
      ;;
      esac
      3、for循环是固定循环,在循环时已知道要循环几次,也称计数循环
      for  变量  in  值1  值2  值3
      do
      程序
      done
      注:in后有几个值就循环几次,每次循环都把值赋予变量
      for  ((初始值;循环控制条件;变量变化))
      do
      程序
      done
      注:初始值,在循环开始时需要给变量赋予初始值,如i=1;循环控制条件,用于指定循环的次数,如i ls.log
      for  i  in $(cat ls.log)
      do
      tar  -zxf $i  &>/dev/null
      done
      rm–rf /lamp/ls.log
      例:#vi  useradd.sh
      #!/bin/bash
      read  -t 30 -p “Please input username: “ name
      read  -t 30 -p “please input the number of users: “ num
      read  -t 30 -p “please input the password: “ pass
      if  [ -n  “$name” –a  -n  “$num”  -a -n  “$pass”  ]
      then
      y=$(echo  $num | sed ‘s/[0-9]//g’)
      if  [  -z  “$y”  ]
      then
      for  ((i=1;i/dev/null
      echo  $pass | /usr/bin/passwd --stdin $name$i  &>/dev/null
      done
      fi
      fi
      4、while循环:只要条件判断式成立,循环就一直继续,直到条件不成立才停止。
      while[  条件判断式 ]
      do
      程序
      done
      5、until循环:条件判断式不成立则进行循环,条件成立,则中止循环。
      until[  条件判断式  ]
      do
      程序
      done
      6、函数:
      function  函数名 () {
      程序
      }
      7、特殊流程控制语句:
      》exit语句:在脚本中是退出当前脚本,#exit 返回值,返回值可自己定义,用$?查询,若没定义返回值,则是执行exit语句之前最后执行的命令的返回值。
      》break语句会结束整个当前循环,而continue语句结束单次当前循环,下次循环会继续
      for  ((条件判断语句))
      do
      程序语句
      break(continue)
      程序语句
      done
      例:#vi  ping.sh
      #/bin/bash
      echo “这个脚本是统计/root/ip.txt所有ip地址的丢包率”
      for  i $(cat  /root/ip.txt)
      do
      aa=$(ping  -c 3 $i | grep ttl | wc  -l)
      bb=$((  3 - $aa ))
      cc=$(echo  “$bb 3” | awk ‘{ print “%5.2f% \n”,$1/$2*100}’)
      echo “$i的丢包率是:$cc”
      done
      注:本文由互联网收集整理(51CTO、360DOC、chinaunix、百度百科、兄弟连免费视频等)。


  • 运维网声明 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-556206-1-1.html 上篇帖子: 监控mysql主从同步并报警的shell脚本 下篇帖子: Shell脚本中利用awk处理大批量数据
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

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

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

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

    扫描微信二维码查看详情

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


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


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


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



    合作伙伴: 青云cloud

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