正则表达式:就是在使用SHELL时匹配字符时的书写规则

通配符(wildcard):表示一组字符的范围
 *  匹配0个或任意多个字符
 ?  匹配任意一个字符
 -  在特定语句表示有序范围,如"A-Z"
 ^  表示一行的开头,在[]里则表示不包含
 $  表示一行的结尾
 [] 字符集匹配,匹配方括号中定义的字符集中的任意一个。
 {} 表示重复
   {n} 表示前一个字符集出现的次数必须为N次
   {n,}表示前一个字符集出现的次数至少为N次
   {n,m}表示前一个字符集出现的次数为N次或M次之间
 \< 表示单词词首
 \> 表示单词词尾
 \   表示前一个字符出现次数为1或多次
 
 ############### sample ###############
  grep '.\{40\}' /usr/share/dict/words #显示长度为40的字符串
  grep '^i.\{18\}n$' /usr/share/dict/words #显示以I开头长度19的字符串
  grep '^a.*e$' /usr/share/dict/words #显示以a开头,E结尾的字符串
  grep '.\{30,\}' /usr/share/dict/words #显示长于30的字符串
  grep -v '^#' /etc/squid/squid.conf | grep -v '^$' # -v反向匹配
  [A-Z]匹配从A到Z的任意一个大写字母
  [^ABC]匹配除了ABC以外的任意一个字母
  [0-9]\{1,2\}-[0-9]\{1,2\}-[0-9]\{4\}   # 日期格式dd-mm-yyyy
  [0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}    #类IP地址格式
 
引用符号:
 "" 双引号用来分隔参数或屏蔽空格
 '' 单引号用来分隔参数或屏蔽所有特殊意义的字符
 `` 反引号用来表示被预先执行的部分,返回值作为其前命令的参数
 ;  分号用来分隔在同一行的多个命令行语句
 \  可以原样引用特殊符号
 #  表示注释行语句
 
元字符(metacharacter):SHELL预定义的特殊字符集
 \   转义字符,其后的表示一个特殊的元字符
 \a    报警铃
 \b    退格
 \cN  ASCII控制字符。比如\cC代表Ctrl C
 \d  10进制数字 ('0' - '9')
 \D  非数字
 \e    Escape
 \f    换页符
 \n    换行符
 \r    回车
 \s  空白符
 \t    水平制表符,TAB
 \v    垂直制表符
 \xnn ASCII码中十六进制代码为NN的字符

过滤器:
 |  将前一个过滤器的输出直接送入后一个过滤器的输入
 1> 标准输出
 2> 错误输出
 <  输入重定向
 >  输出重定向
 >> 追加输出重定向
 << 追加输入重定向 ## cat >> testfile.$$ <<abcd 表示标准输入以abcd结束
 tee 把副本输送到标准输出,另一个副本输出到一个文件中
   who | tee who.out
   who | tee -a who.out  # -a表示追加
 ############### 自动登录FTP且下载文件 ###############
   #!/bin/bash
   echo "ftp server ip: "
   read ftpip
   echo "ftp username: "
   read user
   echo "ftp passwd: "
   read passwd
   ftp -n<<! # -n阻止FTP默认自动登录方式
   open $ftpip
   user $user $passwd
   binary
   ha
   lcd /var
   delete showtec.log 2> /dev/zero
   put showtec.log

流编辑器 SED:非交换式的编辑文件或标准输入导出的文本拷贝
 格式1:sed [options] 'command' file(s)
 格式2:sed [options] -f scriptfile file(s)  
 
 -n 与-e合用时,只输出符合条件的行
    
  e多点编辑命令
    sed -e '1,5d' -e 's/test/check/' install.log   # 第一条命令删除1至5行,第二条命令用check替换test。
    sed -e '/^#/d' -e '/^$/d' install.log   # 删除以#开头的注释行和空行
 
  a追加:在当前行后面加一行
    sed '2a this is a example' install.log   # 在第二行后面追加一行
    sed '/^test/a\this is a example' example   # 以test开头的行后面追加一行"this is a example"
    sed G install.log   # 在每一行后面增加一空行
    sed -e '7a
\\t'  install.log   # 在第七行后加入一空行
    sed -i '7G' install.log   # 在第七行之后追加一空行,-i参数将对文件做修改。
  
  d删除:
    sed '2d' install.log   # 删除第二行。
    sed '2,$d' install.log   # 删除第二行到末尾所有行。
    sed '$d' install.log   # 删除最后一行。
    sed '/test/'d install.log   # 删除所有包含test的行。
    sed -e '1,20{/setup/d}' install.log   # 删除1-20之间包含SETUP字符的行
    sed -e '4,${/setup/d}' install.log | grep "setup"   # 删除4-末尾之间包含SETUP字符的行
  
  i插入:在当前行之前加一行
    sed  '/^aaa/i\this' install.log   # 把指定内容插入匹配行的后面
    sed -e 'i/this is test/g' install.log   # 每行前面都插入一行"this is test"
  
  s替换:通过指定两个字符串,第二个替换第一个
    sed -e 's/one/two/g' install.log   # 在全局范围内one替换为two。
    sed -e '3,$s/^/sonic/' install.log   # 3-最后一行行首插入sonic.
    sed -n 's/^one/two/p' install.log   # 如果某一行以one开头则替换成two,且输出显示。
    sed -e 's/^[ \t]*//;s/[ \t]*$//' install.log   # 删除行首和行尾空格
    sed -e 's/^[0-9]*//g' install.log -e 's/^[ \t]//g'   # 删除行首数字和空格
    sed '/test/,/check/s/$/sed test/' install.log   # test和west之间的所有行,行末用sed test替换。
    sed 's/^11.4.2.1/&-localhost/' install.log   # &符号表示替换换字符串中被找到的部份,变成11.4.2.1-localhost。
    
  y转换:
    sed '1,10y/abcde/ABCDE/' install.log   # 把1--10行内所有abcde转变为大写,注意,正则表达式元字符不能使用这个命令   
    
  p打印:显示
    sed -n '8,12p'   # 打印第8到12行
    sed -n '/setup/!p' install.log   # 打印不包括SETUP的行
    sed -n '/setup/=' install.log   # =的作用是打印包含SETUP的行号
    sed -n '/xorg/p' install.log   # 打印包含XORG的所有行
    sed -n '1,20{/setup/p}' install.log   # 打印1-10行包括SETUP的行
    sed -n '/test/,/check/p' install.log   # 打印test和check之间的所有行。                   
    sed -n '5,/^test/p' install.log   # 打印从第五行开始到第一个包含以test开始的行之间的所有行。
    sed -n '1,10s/\<setup/setup - sed test/p' install.log   # 第1行到10行使用"setup - sed test"替换"setup"并且输出

SHELL编程:

变量:
 1 环境变量:环境变量用于所有用户进程,在所以脚本中可直接调用
   set 查看当前SHELL的所有变量
   env 查看当前SHELL的环境变量
   set -a 导出SHELL变量到环境变量
   export 导出普通变量为环境变量
   unset -a释放所有环境变量
 
 2 SHELL变量:在用户现在的SHELL生命期的脚本中使用
   $ 使用"$"符号引用变量
   = 使用等号给变量赋值
   read -p "Please enter you name:" name 交互式变量赋值 
   unset 释放变量
   echo/printf 显示变量
   ${ variable : -value } 测试变量是否存在,如果未存在则使用指定的值进行初始化)    
 
 3 位置变量:传入脚本的参数数目最多为9个
   $0 脚本名称
   $1 脚本第一个参数
   $2 脚本第二个参数
   .................
   $9 脚本第九个参数
    
 4 特定变量:
   $# 传递到脚本的参数个数
   $* 以一个单字符串显示所有向脚本传递的参数。
   $$ 脚本运行的当前进程ID号
   $! 后台运行的最后一个进程的进程ID号
   $@ 与$#相同,但是使用时加引号,并在引号中返回每个参数
   $- 显示shell使用的当前选项,与set命令功能相同
   $? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
 
 5 下标变量:
   定义下标变量
   aaa=(1000 2000 3000 4000)

   引用下标变量
   echo $aaa   # 输出下标变量中第一个元素的值
   echo ${aaa[0]}
   echo ${aaa[1]}
   echo ${aaa[2]}
   echo ${aaa[3]}
   
   aaa[4]=5000   # 给下标变量中指定元素赋值
   echo ${#aaa[*]}   # 查看有几个元素
   echo ${aaa[*]}   # 输出所有下标变量元素

表达式
 1 字符表达式
   = 等于则为真                 
   != 不相等则为真              
   -z 字符串 字符串长度伪则为真 
   -n 字符串 字符串长度不伪则为真

 2 数字表达式
   -eq:等于则为真
   -ne:不等于则为真
   -gt:大于则为真
   -ge:大于等于则为真
   -lt:小于则为真
   -le:小于等于则为真
   
     两个整数相加
   - 第一个数减去第二个数
   * 两整数相乘
   / 第一个整数除以第二个整数
   % 两整数相除,取余数
    
 3 日期表达式:时间差可转换为秒进行计算机
      %a  以缩写格式显示星期
      %A  以完全格式显示星期
      %b  以缩写格式显示月份
      %B  以完全格式显示月份
      %d  显示日期
      %D  完整日期07/14/09
      %F  完整日期2009-07-14
      %g  显示年份的后两位09
      %G  显示年份2009
      %j  显示当前是一年中的第几天 (001..366)
      %k  显示小时 ( 0..23)
      %l  显示小时 ( 1..12)
      %m  显示月份 (01..12)
      %M  显示分钟 (00..59)
      %N  显示纳秒 (000000000..999999999)
      %p  显示 AM or PM
      %r  显示12小时制时间 (11:11:04 PM)
      %s  显示秒,从1970-01-01 00:00:00 UTC至今
      %S  显示秒 (00..60)
      %t  a tab
      %T  time; same as %H:%M:%S
      %u  数字格式显示星期几 (1..7)
      %V  显示当前是一年中的第几个星期  (01..53)
      %w  day of week (0..6); 0 is Sunday
      %x  (12/31/99)
      %X  (23:13:48)
      %y  年(00..99)
      %Y  year
      %z  timezone (e.g., -0400)
      %:z timezone (e.g., -04:00)      
   
   -d, --date=STRING 按字符串描述显示时间
    date -d "1 day" %Y%m%d
    date -d "2 day" %Y%m%d
    date -d "15 day 10 hour 5 minute 4 second"
    date -d "-1 day 10 hour 5 minute 4 second"
    date -d "-2 day -5 hour -5 minute -4 second"

 4 逻辑表达式
   -a 逻辑与
   -o 逻辑或
   ! 逻辑非
   ############### SAMPLE ###############
   if [ 3 -gt 2 -o 0 -gt 1 ]
    then
     echo "True"
    else
     echo "False"
   fi
 
 5 文件测试表达式
   -e 文件名:文件存在则为真
   -r 文件名:文件存在且可读则为真
   -w 文件名:文件存在且可写则为真
   -x 文件名:文件存在且可执行则为真
   -s 文件名:文件存在且至少有一个字符则为真
   -d 文件名:文件存在且为目录则为真
   -f 文件名:文件存在且为普通文件则为真
   -c 文件名:文件存在且为字符型特殊文件则为真
   -b 文件名:文件存在且为块特殊文件则为真   
    
 6 求表达式的值: expr(expression)
   # expr length "this is a test"  字串长度
   # expr substr "this is a test" 3 5 截取字符从3到5
   # expr index "welcome to Beijing" e  指定字符在字符串中首个匹配的位置
   # expr 20 % 9  余数 

参数传递:还可以使用位置变量向脚本传递参数
 getopts 向主程序传递多个参数
   ------------------------------
   #!/bin/bash
   while getopts ahf: OPTION
    do
      case $OPTION in
      a)
        ALL=true
        echo "ALL is $ALL"
        ;;
      h)
        HELP=true
        echo "HELP IS $HELP"
        ;;
      f)
        FILE=true
        echo "FILE is $FILE"
        ;;
      esac
    done

函数:函数是由若干条shell命令组成的。运行时是一个独立的进程,有自己的退出状态。
  定义函数
   functionname
   {
   若干命令行
   return XXX   ### reture是退出函数,且返回值
   }

  调用函数的格式为
   functionname param1 param2

流程结构

IF判断语句
  if [ 条件1 ]
  then
   命令行1
  elif [ 条件2 ]
   命令行2
  else
   命令行3
  fi

&&和|| ( )
  命令1 && 命令2   ## 命令1成功执行后才能执行命令2
  命令1 || 命令2   ## 命令1未能成功执行,那么执行命令2
  ( 命令1 | 命令2 ) && ( 命令3 )   ## 命令1和2作为一组命令

CASE条件选择
  case "$1" in
   start}
    start
    ;;
   stop)
    stop
    ;;
   status)
    status
    ;;
   restart)
    stop
    start
    ;;
  esac

FOR步长行循环:
  删除APACHE所有进程
   ------------------------------
  AAA="`pgrep httpd`"
  [ -z "$AAA" ] && echo `httpd is not running!` && exit
  for i in $AAA
    do
      kill -9 $i
    done
  echo httpd
  
  从1到100,每秒钟显示一个数字,不换行
   ------------------------------
  for aaa in `seq 1 100`
    do
      echo -n "$aaa "   # -n 不换行
      sleep 1
    done
  
  求从1到100的累加和
   ------------------------------  
  sum=0
  for (( i=1;i<=100;i ))
      do
          sum=$[sum i]
      done
  echo $sum

while和until 循环
  Until是直到某条件成立退出循环,While是当某条件成立继续循环
  while可能一次都不循环,而until至少循环一次
  
  #!/bin/sh
  while [ -f /var/run/ppp0.pid ]
  do
  killall pppd
  done
  
  #!/bin/sh
  until [ -f /var/run/ppp0.pid ]
  do
  sleep 1
  done

  ### 条件为TRUE时为死循环

bash程序的调试
 -e:如果一个命令失败就立即退出
 -n:读入命令但是不执行它们
 -u:置换时把未设置的变量看作出错
 -v:当读入shell输入行时把它们显示出来
 -x:执行命令时把命令和它们的参数显示出来

AWK:它具备了一个完整的语言所应具有的几乎所有精美特性。
  
AWK程序设计模型
 AWK程序框架是由开始(BEGIN),主输入(MANI INPUT),结束(END)组成。
 BEGIN是在MAIN INPUT循环体之前被执行,END是在MAIN INPUT循环体之后被执行。
 其中主输入是一个自动循环体,它将一直重复执行直到输入完成或有一些存在的条件终止它。
 一般主输入的循环次数是和输入的行数相同的,当没有其它行输入时循环将终止。
 所编写的循环体应被应用于每个输入行,且每次一行。
 
 ############### 框架实例 ###############  
 BEGIN {
  system ( "clear" )
  FS = ","  
  sum = 0 
  printf ( "BEGIN" )                  
  }
 {
  for ( i=1;i<-100;i ){
  sum = $sum 1
  printf ($sum,"\t",$1)
   }
  }
 END {
  printf $sum
  printf ( "Finish" )
  }
   
awk的环境变量
 $n      # 当前记录的第n个字段,字段间由FS分隔。
 $0      # 完整的输入记录。
 ARGC     # 命令行参数的数目。
 ARGIND    # 命令行中当前文件的位置(从0开始算)。
 ARGV     # 包含命令行参数的数组。
 CONVFMT   # 数字转换格式(默认值为%.6g)
 ENVIRON   # 环境变量关联数组。
 ERRNO    # 最后一个系统错误的描述。
 FIELDWIDTHS   # 字段宽度列表(用空格键分隔)。
 FILENAME     # 当前文件名。
 FNR     # 同NR,但相对于当前文件。
 FS      # 字段分隔符(默认是任何空格)。
 IGNORECASE    # 如果为真,则进行忽略大小写的匹配。
 NF      # 当前记录中的字段数。
 NR      # 当前记录数。
 OFMT     # 数字的输出格式(默认值是%.6g)。
 OFS     # 输出字段分隔符(默认值是一个空格)。
 ORS     # 输出记录分隔符(默认值是一个换行符)。
 RLENGTH   # 由match函数所匹配的字符串的长度。
 RS      # 记录分隔符(默认是一个换行符)。
 RSTART    # 由match函数所匹配的字符串的第一个位置。
 SUBSEP    # 数组下标分隔符(默认值是\034)。

 

AWK运算符  
 数学运算符
      # 将数字相加
  -   # 减
  *   # 乘
  /   # 除
  ^   # 执行指数运算
  %   # 提供模
     # 将变量值加一
   =  # 将其他操作的结果分配给变量
  —   # 将变量减一
  -=  # 将减法操作的结果分配给变量
  *=  # 分配乘法操作的结果
  /=  # 分配除法操作的结果
  %=  # 分配求模操作的结果
   
 逻辑运算符
  && #  逻辑与
  || #  逻辑或
  !  #  逻辑非
   
 关系运算符
  <  #  小于
  >  #  大于
  <= #  小于或等于
  >= #  大于或等于
  == #  相等
  != #  不等
  ~  #  匹配
  !~ #  不匹配

 

AWK函数  
 数学函数
  exp(x)   # 求幂
  int(x)   # 取整
  rand()   # 随机数
  sin(x)   # 正弦
  sqrt(x)  # 平方根
  srand(x) # x是rand()函数的种子
  int(x)   # 取整,过程没有舍入
  rand()   # 产生一个大于等于0而小于1的随机数
  
 字符串函数
  gsub(r,s)     # 在整个$0中用s替代r 
  gsub(r,s,t)   # 在整个t中用s替代r
  index(s,t)    # 返回s中字符串t的第一位置
  length(s)     # 返回s长度
  match(s,r)    # 测试s是否包含匹配r的字符串
  split(s,a,fs)   # 在fs上将s分成序列a 
  sprint(fmt,exp) # 返回经fmt格式化后的exp 
  sub(r,s)      # 用$0中最左边最长的子串代替s 
  substr(s,p)    # 返回字符串s中从p开始的后缀部分
  substr(s,p,n)   # 返回字符串s中从p开始长度为n的后缀部分
  tolower(s)   #  字符串大写转小写
  toupper(s)   #  字符串小写转大写

 

 日期函数
  strftime函数使用C库中的strftime函数格式化时间
  格式:systime( [format specification][,timestamp] )
  -------------------------------------------------
  %a   # 星期几的缩写(Sun)
  %A   # 星期几的完整写法(Sunday)
  %b   # 月名的缩写(Oct)
  %B   # 月名的完整写法(October)
  %c   # 本地日期和时间
  %d   # 十进制日期
  %D   # 日期 08/20/99
  %e   # 日期,如果只有一位会补上一个空格
  %H   # 用十进制表示24小时格式的小时
  %I   # 用十进制表示12小时格式的小时
  %j   # 从1月1日起一年中的第几天
  %m   # 十进制表示的月份
  %M   # 十进制表示的分钟
  %p   # 12小时表示法(AM/PM)
  %S   # 十进制表示的秒
  %U   # 十进制表示的一年中的第几个星期(星期天作为一个星期的开始)
  %w   # 十进制表示的星期几(星期天是0)
  %W   # 十进制表示的一年中的第几个星期(星期一作为一个星期的开始)
  %x   # 重新设置本地日期(08/20/99)
  %X   # 重新设置本地时间(12:00:00)
  %y   # 两位数字表示的年(99)
  %Y   # 当前月份
  %Z   # 时区(PDT)
  %%   # 百分号(%)
   
  ############### SAMPLE ############### 
  $ awk '{ now=strftime( "%D", systime() ); print now }'
  $ awk '{ now=strftime("%m/%d/%y"); print now }'
     
 其它函数
  close
  system
  getline

 自定义函数
  function name ( parameter, parameter, parameter, ... ) {
   statements
   return expression # 返回语句
   }  
       
格式化打印
 格式:printf ( format_expression,[arguments])
 c   #  ASCII字符
 i   #  十进行整数
 f   #  浮点格式
 O   #  无字符的八进制
 s   #  字符串宽度(width)
 x   #  无符号的十六进制,用a-f表示10-15
 X   #  无符号的十六进制,用A-F表示10-15
 %   #  字面字符%

 ############### SAMPLE ###############
  printf ( "|%-10s|\n" , "hello" )   # 输出宽度为10,左对齐的字符
  printf ( "%*.*g\n", 5, 3, myvar )   # 动态的指定宽度和精度用星号表示,宽度是5,精度是3
  printf ( "%.2f", 2.567 )   # 输出2.57
  printf ("%i",108.9)   # 输出108
  
流程结构
 if/else else if语句
  if (expression){
   statement; statement; ...
   }
  else if (expression){
   statement; statement; ...
   }
  else if (expression){
   statement; statement; ...
   }
  else {
   statement; statement; ...
   }

 for步长循环语句
  for (item in arrayname){
   print arrayname[item]
    }
  
  for ( i=1;i<=100;i ) {
   statement; statement; ...
   }
 
 while条件循环语句
  while (expression){
   statement; statement; ...
   }

  awk -F: 'BEGIN {iii=0} { if ($7=="/sbin/nologin") iii =1 } END { print iii }' /etc/passwd
  chkconfig --list | awk 'BEGIN {iii=0} { if($5=="3:启用") iii =1 } END { print iii }'

LINUX开机流程
 1 加电BIOS自检:检测CPU,内存,显卡,一其它一些外围设备
 2 BIOS选择首选启动设备,引导MBR
 3 MBR引导BOOTLOAD的第二阶段GRUB
 4 GRUB根据GRUB.CONF的配置文件载入内核核心内容(硬件检测,设备驱动,RO挂载根目录,加载init进程)
 5 INIT程序根据INITTAB初始化系统运行级别
 6. init 执行 /etc/rc.d/rc.sysinit 档案;
 7. 激活核心的外挂式模块 (/etc/modules.conf);
 8. init 执行 runlevel 的各个服务配置脚本(/ETC/rcX.d/* 和 /ETC/INIT.D/*的脚本是一致的)
 9. init 执行 /etc/rc.d/rc.local脚本;  
 10 RC.SYSINIT初始化SHELL环境
 11 /ETC/PROFILE
 12 ~/.BASHRC
 13 ~/.BASH_PROFIEL
 
 其中6,7,8,9,11,12,13到可以加入脚本。
 脚本可集中存储到一个目录,然后把这个路径追加赋值到PATH环境变量中。
 PATH被追加赋值后的好处是运行脚本时不需写路径信息。