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

[经验分享] 20150913 Linux Shell

[复制链接]

尚未签到

发表于 2018-5-22 07:22:19 | 显示全部楼层 |阅读模式
  Part 1 学习整理
  第一、shell概述
  Bshell是解释器
  硬件—》Kernel--->库----》程序员调用库进行程序开发
  守护进程,服务进程(后台运行、非交互):启动?开机时自动启动;   
交互式进程:shell应用程序  
   广义接口:GUI,CLI  
   GUI  
   CLI:  
     promt  
       COMMAND
  词法分析: 命令,选项,参数  
            内建命令:shell自带  
            外部命令:PATH环境变量所定义
  fork() 创建为一个进程;系统调用的一种实现
  把要运行的一系列命令,写在文件中;解释器读取文件,逐条运行。
  脚本或程序源文件:文本文件,由文本文件由机器执行的方式  
  两种方式:  
   编译执行:预处理-->编译-->汇编-->链接;事先完成,结果:二进制程序文件  
             C, C++  
   解释执行:由解释器全程参与运行过程,无需要事前转换。每次读取一行,运行一行;  
             Python:编程库  
             程序控制结构,调用编程库完成程序编写;  
         库文件:功能模块,在编程中可调用;通过其API;  
            Bash:编程(交互式接口,提供编程的能力)
  程序控制结构,调用机器上命令程序文件进行程序编写;例如ls、Cat等
  这些命令可脱离shell执行。相关程序文件不依赖程序库  
            外部命令:各GNU应用程序提供
  第二、程序编程方式
  程序:指令+数据   
    算法+数据结构
  过程式编程:以指令为中心,设计算法,数据服务于算法;   
    对象式编程:以数据为中心,设计数据结构(类),程序服务于数据结构;应用大于
  bash过程式编程:   
        顺序执行:逐个执行     
        选择执行:只执行其中一个分支     
        循环执行:一段代码要执行0,1或多遍
  编程元素:变量、流程、函数
  第三:shell变量的定义
  A:变量作用范围
  变量:可变化的量,命名内存空间
  一个脚本一个进程运行,一个进程内部多个函数,每个函数
  内部可使用局部变量,作用范围某函数执行过程。   
    bash环境:作用范围     
        本地变量:当前shell进程;     
        环境变量:当前shell进程及其子进程;     
        局部变量:某个函数执行过程;     
        位置参数变量:在脚本中引用传递给脚本的参数;在函数中引用传递给函数的参数;     
        特殊变量(内建某些特殊值):$?, $*, $@, $#, $$
  B:变量值类型     
     数值,字符;     
         数值:(每种类型有单独的内存存储空间)     
             整数     
             浮点数     
         字符:     
             ASCII码(7位2进制数)
  数值与字符的区别:   
             字符:1, 2, 0(每个字符8个2进制数)     
             数值:120 --> 转换成2进制数(7位2进制)
  变量类型的作用:   
            存储空间     
            运算     
            存储格式
  语言对变量类型的支持力度:   
            强类型:C++(类型严格区分)     
            弱类型:变量类型不严格区分;     
                 默认存储机制:bash为字符,也可指定为数值型
  C:bash变量的定义使用
  bash的变量使用特点:弱类型、无须事先声明;   
1)本地变量:只在本进程有效,在父进程无效
  示例:运行二个bash,第一个为父进程、第二个为子进程
  父进程定义变量$animal,echo $animal输出为pig,而在
  子进程运行输出echo $animal为空
DSC0000.jpg

  name=value   如果为字符串需引号(单引号或双引号皆可)括起来,如无空格可直接使用  
     name: 变量名  
      =:赋值符号  
       value:值
  变量名:只能包含数字、字母和下划线;且不能以数字开头;(不要使用大写开头)   

  引用变量:${name}, $name,返回值用echo ${name}
  引用(共4种,常用三种如下):  
      弱引用: "", 其内部的变量引用会被替换为变量值;(变量替换会发生)  
      强引用:'',其变量的变量引用会保持原有字符;  
      命令引用:`COMMAND`, $(COMMAND),引用命令的执行结果;反引号` `
  声明为整型:  
        declare -i name[=value]  
        let name=value
  查看所有变量:set
  生命周期:  
       创建:开始  
      销毁:(销毁法则)  
        自动销毁:shell进程终止;  
        手动销毁:unset name(变量名)
  2)环境变量:
      作用范围当前进程及子进程     
    被“导出”的本地变量     
        export name[=value]     
        declare -x name[=value]
  示例:name=’obama’ #这里为本地变量
  exprot name   #导出后为环境变量
DSC0001.jpg

  分别进入三个bash子进程,使用echo $name
  正常可以输出相关值obama
DSC0002.jpg

  查看所有环境变量:env, printenv, export
DSC0003.jpg

  销毁:(手动、自动)   
   unset name
  第四、脚本:文本文件  
  运行脚本:事实上是运行一个bash进程,此进程负责从脚本文件中读取一个执行逻辑,
  而后由bash进程负责解析并运行此逻辑;脚本作为参数提供bash运行。   
1)启动脚本:
  两种方式:     
    (1) # bash /PATH/TO/SCRIPT_FILE     bash加路径     
    (2) 一个执行权限, (单独运行)   # ./PATH/TO/SCRIPT_FILE
  语法格式:
  shebang语法:第一行顶格写)  
      #!/bin/bash   (解释器路径,运行下而脚本中内容)
  第一行:顶格给出shebang   
    注释行:#
  脚本示例:执行或者./shell名称(之前增加执行权限)
DSC0004.jpg

  *备注:--stdin表示可以用任意文件做标准输入,这里是echo
  其中第一个testuser1是为密码,后利用—stdin进行引用
  2)bash的常用选项:  
    -n: 检查脚本中的语法错误;  
    -x:调试执行脚本;
  bash  脚本名称:直接运行
DSC0005.jpg

  3)命令状态结果:  
  bash进程用于追踪执行的命令成功与否的状态:  
     0: 成功  
     1-255:失败(其中1、2、127、63、64是bash内置其它可自定义)
  特殊变量:  
     $?:上一条命令的执行状态结果;
DSC0006.jpg

  布尔型:  
     “真”:成功  
     “假”:失败
  自定义脚本的状态结果:  
       exit [n]
  注意:脚本中任何位置执行了exit命令即会终止当前shell进程;
DSC0007.jpg

  4)条件测试:   
  界定程序执行环境;
  (1) 根据运行的命令的状态结果; 根据结果$?返回值进行判断!结果成功或失败  
  (2) 测试表达式  
    test EXPRESSION    例如:  
     [ EXPRESSION ]   注意:[ ]内部前后二端有空格,无空格会提示语法  内建命令  
     ` EXPRESSION `    同样需要空格,bshell关键字
  测试表达式常规包括以下三种:
  第一种:整数测试:双模操作符,隐含着做数值大小比较,所以不要给变量引用加引用
  $A -gt $B:是否大于;是则为“真”,否则为“假”;   A变量中的数值是否大于B变量的值
DSC0008.jpg

  返回非0说明是假的  
    $A -ge $B: 是否大于等于;  
    $A -lt $B:是否小于; (less then)  
    $A -le $B: 是否小于等于;   
    $A -eq $B: 是否等于; (equal)  
    $A -ne $B:是否不等于;
  第二种:字符串测试:ASCII码比较数值越大,字符比较时其值越大;
  有变量双引号、无变量单引号,同时采用双引号  
    "$A" > "$B":是否大于;  
    "$A" < "$B":是否小于;  
  "$A" == "$B":是否等于; 比较常用
DSC0009.jpg   
  "$A" != "$B":是否不等于;  
  -z "$A":是否为空;空则为“真”,否则为“假”  
  -n "$A":是否不空;不空则“真”,空则为“假”

  注意:应该使用双中括号` EXPRESSION `
  第三种:文件测试:测试文件的存在性以及属性;单目操作符   
     -e $file: 是否存在;存在则为“真”,否则为“假”; 后面$file为文件路径  
     -a $file: 同上;  
     -f $file:文件是否存在且为普通文件;  
     -d $file:文件是否存在且为目录;  
     -h $file:是否存在且为符号链接文件;  
     -L $file: 同上  
     -b $file:是否存在且为块设备文件;  
     -c $file:是否存在且为字符设备文件;  
     -S $file:是否存在且为套接字文件;  
     -p $file: 是否存在且为管道文件;
  第四种:权限测试
  -r $file: 当前用户对文件是否拥有读权限;  
   -w $file:当前用户对文件是否拥有写权限;  
   -x $file:当前用户对文件是否拥有执行权限;
  -u $file:文件是否拥有SUID权限;  
   -g $file:文件是否拥有SGID权限;  
   -k $file:文件是否拥有sticky权限;
  -O $file: 当前用户是否为指定文件的属主;  
  -G $file: 当前用户是否为指定文件的属组;
  示例:
DSC00010.jpg

  第五种:双目操作符: (二个操作符)  
$file1 -nt $file2: file1是否新于file2, file1的最近一次的修改时间戳是否晚于file2的; (new then)  
$file1 -ot $file2: file1是否旧于file2, file1的最近一次的修改时间戳是否早于file2的; (old then)  
$file1 -ef $file2:file1与file2是否指向了同一个inode;测试二者是否为同一个文件的硬链接;
  第六种:特殊设备:  
/dev/null: 空,bit buckets,吞下所有数据,并直接丢弃; ,作为输出设备使用
  示例    &>/dev/null  
/dev/zero:吐出一堆0;作为输入设备作用
  5) bash之条件判断(选择执行):
  包括顺序、选择、if/then, case ,fi结尾
  单分支:
  if CONDITION; then  
      if-true-分支  
  fi
  多分支:
  if CONDITION; then  
    if-true-分支     
       else  
   if-false-分支  
  fi
  取反
  ! CONDITION: 取反
DSC00011.jpg

DSC00012.jpg

  上述示例中如果条件为假,则不运行后续”echo $username|….”命令
  
练习:写一个脚本  
如果某路径不存在,则将其创建为目录;否则显示其存在,并显示内容类型;  

      #!/bin/bash  
      #  
      filename="/tmp/x/y/z/testdir"  
         if [ -e $filename ]; then  
             echo "$filename exists."  
             file $filename  
        else  
           mkdir -p $filename   #-P表示父目录同时创建  
         fi  6)脚本参数(位置参数变量):  
  # ./script.sh /etc/fstab /etc/grub2.cfg (centos 7)  
             $0          $1          $2
  位置参数变量:$1, $2, ...  
      ${10}  二位数字即超过10时中{}
  示例:判断输入的文件是否存在?如果存在则计算行数
  如果不存在则输出不是文件
DSC00013.jpg

  运行利用shell名称  filename形式  ./file2.sh /etc/fstab
  ./file2.sh为脚本,/etc/fstab为变量$1的值
DSC00014.jpg

  特殊变量:判断参数是输入   
     $?: 命令的状态结果;
  $0:表示脚本名称  
     $#: 传递给脚本或函数的参数的个数;  
     $*和$@: 引用传递给脚本或函数的参数列表;
  示例:$#用于判断./shell.sh文件后面是否输入参数
  当空时输出Usage:./shell.sh <file>./shell.sh后面要有参数文件路径。
  exit 1条件不满足出退出当前shell脚本
  当有路径参数时正常输出。
DSC00015.jpg

  shift [n]:轮替
  例如有三个参数   1,2,3,当启用该参数时,第一次用完后将参数1
  替出,这时参数为2,3,原用参数前移一位。以此类推。
  示例如下:
DSC00016.jpg

  $*表示所有引用参数
  每次引用$1后,shift后后续变量前移。分别以A,B,C输出,
  $*输出最后一个C。shift 2 表示一次踢2个例如,一般用于
  循环环境中。
DSC00017.jpg

  与用户交互:   
  read命令: read从输入中读取保存到指定变量当中
  help read查看命令  
   read [options] VAR...  
        -p "PROMPT"    提示符  
        -t timeout   超时时间
DSC00018.jpg

  上面将文件路径分别保存到变量file1、 file2中
  在交互输入中包括二种状态
  第一种情况:交互输入的值在于变量
  当给定的变量与输入不匹配时,自左至右分别赋值,
  把剩余给最后一个变量 。示例如下:,将debug message给变量b
DSC00019.jpg

  第二种情况 :变量值大于交换输入的值,后续的变量将不会赋值。
  输出则为空。示例:变量a ,b 赋值,c为空
DSC00020.jpg

  在交互前输入相关提示信息,read可利用-p选项
  echo –n  输入不换行
DSC00021.jpg

DSC00022.jpg

  示例:
       #!/bin/bash           #
            read -p "Plz enter a username: " -t 5 username
            if [ -z "$username" ]; then   #变量值为空值则赋默认值为myuser                     username="myuser"                 fi
            if id $username &> /dev/null; then   #如果用户存在则输出                    echo "$username exists."                 else                     useradd $username                 fi  7) 命令引用: 引用命令的执行结果     
        `COMMAND`, $(COMMAND)
  引用命令的执行结果;
  (1) ls `which cat`     which cat的结果作为ls的参数使用   
        (2) lines=$(wc -l /etc/fstab | cut -d' ' -f1)   变量赋值
DSC00023.jpg

  将结果15赋给变量lines
  示例:
            #!/bin/bash  
            #
            if [ -f $1 ]; then     
             lines=$(wc -l $1 | cut -d' ' -f1)                                       echo "$1 has $lines lines."   
             else               
              echo "$1 not exists or not a file."                                       fi  练习:写一个脚本,完成如下功能;   
   判断给定的两个数值,孰大孰小;     
    给定数值的方法:脚本参数,命令交互;
  #!/bin/bash   
  #   
  read -p "Plz enter two integer: " -t 10 num1 num2
    if [ -z "$num1" ]; then           
      echo "Plz give two integers."         
       exit 1               
    fi
    if [ -z "$num2" ]; then   
      echo "Plz give tow integers."   
      exit 1               
   fi
   if [ $num1 -ge $num2 ]; then   
     echo "Max: $num1, Min: $num2."     
     else           
     echo "Max: $num2, Min: $num1."   
   fi  8)循环语句:  
内置三种循环语句:for, while, until
  第一:定义
  循环:将循环体代码执行0、1或多次;  
         进入条件:进入循环的条件;  
         退出条件:循环终止的条件;
  第二:语法定义
  A)语法结构
  for VARIABLE in LIST; do  
             循环体   
        done  (到此结束)
  LIST:是由一个或多个空格或换行符分隔开的字符串组成;  
     把列表的每个字符串逐个赋值给VARIABLE表示的变量;
  示例:
  for username in user1 user2 user3; do   
                循环体     
            done
  user1给username赋值
  进入条件:列表非空; (将user1、至user3为进行条件)   
        退出条件:列表遍历结束;(到最后一个变量)
  示例:
            添加10个用户,user1-user10;
                #!/bin/bash   
                #      
                for username in user1 user2 user3 user4 user5; do                         if id $username &> /dev/null; then                                  echo "$username exists."                                           else  
                    useradd $username                                               echo "Add user $username finished."                               fi              
                done  B)LIST的生成方法  
   Part 1:(1) 整数列表  
     (a) {start..end}  
     (b) $(seq [start `step` end)    整数步进方式(seq是内部命令)默认从1开始
  例如:seq 10 ,自动生成1-10,或者seq 10 20  自动生成10-20
  seq 1 2 10 表示从1开始,到10结束,步进为2,这样输出为1,3,5,7,9奇数
  seq 2 2  10 表示输出2,4,6,8,10 偶数  
    (2) 直接给出列表  
    (3) glob   (文件名、通配方式)  
   (4) 命令生成  (命令输出为列表,以空格或换行符组成的都为列表)
  示例1:数值列表  
     #!/bin/bash  
     #  

        for i in {1..10}; do  
              if id user$i &> /dev/null; then  
                  echo "user$i exists."  
              else  
                  useradd user$i  
              echo "Add user user$i finished."  
             fi  
       done  
     示例2:glob

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

#!/bin/bash  
#  
           for filename in /var/log/*; do  
                 file $filename  
           done  示例:命令生成列表3 ,判断用户基本组的组名,
  其中$(cut -d: -f1 /etc/passwd)为命令引用  

#!/bin/bash  
#
for username in $(cut -d: -f1 /etc/passwd); do     
  echo "$username primary group: $(id -n -g $username)."
   #备注:$(id -n -g $username)表示命令结果放到此处
done  Part 2 算术运算
       let命令
  算术运算符       +, -, *, /, %, **
  (1) $[$A+$B]   求和 $[  ]   
   (2) $(($A+$B))   $((   ))   与$ [ ] 结果相同  
   (3) let VARIABLE=$A+$B     let命令需要赋值后引用,方式(1)(2)不需要赋值
  示例:a=3  b=4 (赋值)
  let sum=$a + $b
  echo $sum
DSC00024.jpg   
  (4) VARIABLE=$(expr $A + $B)       expr命令引用,引用后给变量

DSC00025.jpg

  expr 后面需要空格
  示例:求100以内所以正整数之和;   

#!/bin/bash   
#
   declare -i sum=0     申明变量,给初始值
  for i in {1..100}; do   
     sum=$[$sum+$i]     
    done
  echo $sum  练习:求100以内所有偶数之和;   
      使用至少三种方法实现;
#!/bin/bash
#      
   declare -i sum=0
    for i in $(seq 0 2 100); do
      sum=$(($sum+$i))
    done
     echo "Even sum: $sum."  

#!/bin/bash  
#
  declare -i sum=0
   for i in {1..100}; do
      if [ $[$i%2] -eq 0 ]; then
         sum=$[$sum+$i]                     
      fi
   done
echo "Even sum: $sum."  Part3 增强型赋值:  
+=      自身赋值  
      sum=$[$sum+$i]  
      let sum+=$i  (help let)
  -=, *=, /=, %=   (除、取模)
  let count=$[$count+1]   --> let count+=1 --> let count++    自动+1  
      let count=$[$count-1] --> let count-=1 --> let count--   自动减1
  示例:显示/etc目录下所有普通文件列表,而后统计一共有多少个文件;
#!/bin/bash   
#   
declare -i count=0
     for file in /etc/*; do            
       if [ -f $file ]; then               
         let count++           
         echo "$count $file"           
       fi
      done
          echo "Total: $count files."  Part 4 测试表达式:  
    整数测试:-gt  大于, –lt 小于, -ge, -le, -eq, -ne  
    字符串测试:==, >, <, !=, –z  是否为空, -n, 是否不空
  =~   左侧字符串可以右侧给的模式匹配
  注意:  
(1) 字符串等时比较测试:用单括号,同时== 二侧有空格  示例: [ "$hostname" == 'localhost'  ]  
(2) 模式匹配测试:[[ "STRING" =~ PATTERN ]]    必须在双括号中,同时=~ 二侧需要有空格
  判断左侧变量字符串与右则匹配
DSC00026.jpg

  . 表示单个字符,需要转译符\.    \.txt$  以.txt结尾
  组合测试条件:  
   条件间逻辑运算:  
       与:多个条件要同时满足;  
       或:多个条件满足其一即可;  
       非:对指定的条件取反;
  表达式组合:  
    与:` CONDITION1 -a CONDITION2 `  
    或:` CONDITION1 -o CONDITION2 `  
    非:[ ! CONDITION ]    CONDITION为表达式
  命令组合:  
    与:COMMAND1 && COMMAND2  <-- [ EXPR1 ] && [ EXPR2 ]  
   或:COMMAND1 || COMMAND2  
   非:! COMMAND
  短路操作符:&&   如果前为真后为真,如果前为假后为假  
          false && true = false  
         false && false = false
  true && false = true  
         true && true = true
  示例:如果id $username &>/dev/null有这个用户则输出用户
DSC00027.jpg

  if COMMAND1; then  
                   COMMAND2  
              fi
  短路操作符:||    如果第一个为真,都为真,(或)  
          true || true = true  
          true || false = true
  false || true = true  
          false || false = false
  示例:如果每个用户不存在,添加一个新用户
DSC00028.jpg

  if ! COMMAND1; then  
               COMMAND2  
           fi
  示例:
DSC00029.jpg

  如果command1为真则执行command2,不执行command3
  如果command1为假,则执行command3
  COMMAND1 && COMMAND2 || COMMAND3
  与下而if执行的结果相同(&& 的优先级高于 || )  
          if COMMAND1; then  
                  COMMAND2  
           else  
                  COMMAND3  
           fi
  
示例:写一个脚本实现如下功能;  
获取当前主机的主机名;  
如果当前主机的主机名为空,或者为localhost,则将其修改为www.magedu.com  

#!/bin/bash         
#           
hostname=$(hostname)   #红色为主机名
        if [ -z "$hostname" -o "$hostname" == "localhost" ];
           then               
           hostname www.magedu.com         
        fi  练习:写一个脚本  
     (1) 传递两个文本文件路径给脚本;  
     (2) 显示两个文件中空白行数较多的文件及其空白行的个数;  
     (3) 显示两个文件中总行数较多的文件及其总行数;
  首先定义二个文件,分别为file1,file2,路径为/tmp/51cto/mkshell/
  脚本如下:用read –P 读取文件路径,四个条件分别赋值进行比较
DSC00030.jpg

  练习:写一个脚本  
    (1) 提示用户输入一个字符串;  
    (2) 判断:  
     如果输入的是quit,则退出脚本;  
     否则,则显示其输入的字符串内容;
DSC00031.jpg

  练习:写一个脚本,打印九九乘法表;
  循环嵌套
  1X1=1  
    1X2=2 2X2=4  
    1X3=3 2X3=6 3X3=9
    #!/bin/bash  
    #  
    for j in {1..9}; do  
      for i in $(seq 1 $j); do      表示从1至j结束  
       echo -n -e "
               ${i}X${j}=$[$i*$j]\t"  -n表示不换行红色标记部分为输出字符 \t表示制表符  
      done  
      echo  
    done  9) 多分支的if语句:  
   单分支:  
        if CONDITION; then  
             if-true-分支  
        fi
  双分支:  
       if CONDITION; then  
           if-true-分支  
       else  
          if-false-分支  
       fi
  多分支:  
        if CONDITION1; then  
           if-CONDITION1-true-分支  
        elif CONDTION2; then  
          if-CONDITIO2-true-分支  
         ...  
        else  
          if-ALL-false-分支   #都不满足的情况  
          fi
  示例:通过脚本参数传递一个文件路径给脚本,判断其类型;
  采用引用的方式  
          #!/bin/bash  
          #  
           if [ $# -lt 1 ]; then    #判断是否为空  
              echo "Usage: $0 <path>"   #为空用脚本+路径方式输入  
              exit 1  
            fi
  if [ -f $1 ]; then  
                 echo "Rgular file."  
            elif [ -d $1 ]; then  
                echo "Directory."  
             elif [ -h $1 ]; then  
               echo "Symbolic link."  
             elif [ -b $1 ]; then  
                echo "Block special."  
             elif [ -c $1 ]; then  
                echo "Charactoer special."  
             elif [ -S $1 ]; then  
                 echo "Socket file."  
              else  
                 echo "file not exist or unknown type."  
              fi
  示例:脚本可接受四个参数  
        start: 创建文件/var/lock/subsys/SCRIPT_NAME  
        stop: 删除此文件  
         restart: 删除此文件并重新创建  
         status: 如果文件存在,显示为"running",否则,显示为"stopped"
  basename命令:  
              取得路径的基名;
#!/bin/bash            
#         
prog=$(basename $0)   #表示引用命令的结果 $0命令获取自己的其名         
lockfile="/var/lock/subsys/$prog"         
#echo $lockfile
  if [ $# -lt 1 ]; then     #不能为空               
    echo "Usage: $prog start|stop|restart|status"                 
    exit 1         
  fi
  if [ "$1" == "start" ]; then               
     if [ -f $lockfile ]; then                  
     echo "$prog is started yet."               
       else     
               touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."                 
          fi            
           elif [ "$1" == 'stop' ]; then                 
          if [ -f $lockfile ]; then                    
  rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."       else                  
             echo "$prog is stopped yet."                 
           fi                     
          elif [ "$1" == 'restart' ]; then                 
              if [ -f $lockfile ]; then                    
                 rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."                 
              else                    
          touch $lockfile && echo "$prog is stopped, Starting $prog ok...."                  
          fi                     
        elif [ "$1" == 'status' ]; then                  
          if [ -f $lockfile ]; then                     
            echo "Running..."                  
            else                     
            echo "Stopped..."                  
          fi                     
           else                    
              echo "Usage: $prog start|stop|restart|sttus"                     exit 1   代表非正常退出                     
           fi  10)case语句  
    简洁版多分支if语句;                 
   使用场景:判断某变量的值是否为多种情形中的一种时使用;

  语法:   
            case $VARIABLE in     
            PATTERN1)     
                分支1     
                ;;     
            PATTERN2)     
                分支2     
                ;;     
            PATTERN3)     
                分支3     
                ;;     
            ...     
            *)     
                分支n     
                ;;     
            esac
  PATTERN可使用glob模式的通配符:   
                *: 任意长度的任意字符;     
                ?: 任意单个字符;     
                []: 指定范围内的任意单个字符;     
                a|b: 多选1;
  示例:提示键入任意一个字符;判断其类型;  

#!/bin/bash     
#     
read -p "Plz enter a character: " char
   case $char in
   [a-z])            
      echo "A character."
      ;;      
   [0-9])            
      echo "A digit."
      ;;           
   *)      
   echo "A special character."
   ;;
   esac  

  示例:脚本可接受四个参数  
   start: 创建文件/var/lock/subsys/SCRIPT_NAME  
   stop: 删除此文件  
   restart: 删除此文件并重新创建  
   status: 如果文件存在,显示为"running",否则,显示为"stopped"
#!/bin/bash      
#      
prog=$(basename $0)        
lockfile="/var/lock/subsys/$prog"        
#echo $lockfile
  if [ $# -lt 1 ]; then               
    echo "Usage: $prog start|stop|restart|status"         
    exit 1         
  fi
case $1 in         
start)              
    if [ -f $lockfile ]; then                  
       echo "$prog is started yet."               
         else           
         touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."              
    fi               
    ;;               
  stop)            
    if [ -f $lockfile ]; then               
       rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."             else              
       echo "$prog is stopped yet."              
     fi              
     ;;              
   restart)              
      if [ -f $lockfile ]; then                 
        rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."              else               
        touch $lockfile && echo "$prog is stopped, Starting $prog ok...."            fi               
       ;;              
    status)               
       if [ -f $lockfile ]; then                  
          echo "Running..."               
          else                  
          echo "Stopped..."                 
       fi                 
       ;;               
    *)                  
    echo "Usage: $prog start|stop|restart|sttus"                  
       exit 1               
    esac  11)流程控制:      
        循环语句:for, while, until

  A)while循环:
  while针对次数未知情况,通过控制变量进行控制
  sleep 5 睡眠5秒钟
  while CONDTION; do   
                循环体     
            done
  进入条件:当CONDITION为“真”;   
            退出条件:当CONDITION为“假”;
  while CONDITION; do   
                循环体     
                控制变量的修正表达式     
            done
  示例:求100以内所有正整数之和;
  #!/bin/bash   
                #     
                declare -i sum=0     
                declare -i i=1
  while [ $i -le 100 ]; do   
                    let sum+=$i     
                    let i++     
                done
  echo "Sum: $sum."
  练习:分别求100以内所有奇数之和,及所有偶数之和;
  奇数之和
  示例:
#!/bin/bash   
#     
declare -i sum=0     
declare -i m=1
while [ $m -le 10 ];do   #小于等于10,控制循环        
   if [ $[$m%2] -eq 1 ];then   #%2表示取模,为1代表奇数,0代表偶数         
     sum=$[$sum+$m]         
        fi         
    let m++     
done
echo "oushu sum is :$sum"   
#示例:打印九九乘法表                    
#!/bin/bash                    
#                     
declare -i i=1                     
declare -i j=1
while [ $j -le 9 ]; do                        
     while [ $i -le $j ]; do                                 echo -e -n "${i}X${j}=$[$i*$j]\t"                             let i++                        
     done                        
       echo                        
       let i=1                        
       let j++                     
  done  B)unitl循环:     
      until CONDITION; do     
           循环体     
           循环控制变量的修正表达式     
          done
  进入条件:当CONDITION为“假”时   
           退出条件:当CONDITION为“真”时
  示例:求100以内所有正整数之和   

#!/bin/bash                     
#                     
declare -i sum=0                     
declare -i i=1
   until [ $i -gt 100 ]; do                        
       let sum+=$i                        
       let i++                     
    done
  echo "Sum: $sum."  练习1:分别求100以内所有偶数之和,以及所有奇数之和;
DSC00032.jpg      
            练习2:实现九九乘法表;

DSC00033.jpg DSC00034.jpg      
练习3:分别使用while和until循环实现添加10个用户:user1-user10;

  使用while循环:(用小于等于le进行判断)
DSC00035.jpg DSC00036.jpg

  使用until循环:(使用-gt 大于进行判断)
DSC00037.jpg     DSC00038.jpg

   12)循环控制:  
     continue [n]:提前结束当前本轮循环,而直接进入下一轮;   
     break [n]:提前结束循环;(当前上一次循环)
  while循环:  
            while CONDITION; do  
                 .......  
               if CONDITION2; then  
                   break [n]  
               fi  
            done
  while CONDITION; do  
                ......  
               if CONDITION2; then  
                     continue [n]  
               fi  
                 ......  
          done
  示例:求100以内所有偶数之和;(-le 小于等于 )
#!/bin/bash         
#         
declare -i sum=0         
declare -i i=0
  while [ $i -le 100 ]; do                  
    let i++                 
     if [ $[$i%2] -eq 1 ]; then   #等于1为奇数                              echo "$i is a odd."                 
       continue  #遇到后面的代码不执行,重新进入while循环               
     fi                  
     let sum+=$i            
   done
   echo "Sum: $sum."  死循环:  
           while true; do    (当真循环,为假时退出)     
                循环体     
                if CONDTION; then     
                    break     
                fi     
            done
  until false; do   (当假循环,为真时退出)   
                循环体     
                if CONDITION; then     
                    break     
                fi     
            done
  示例:每隔3秒钟查看当前系统上是否有名为“gentoo”的用户登录;  
  如果某次查看gentoo登录了,则显示gentoo已经登录;  
  如果未登录,就显示仍然未来,并显示这是已经是第多少次查看了;
#!/bin/bash      
#      
username=$1      
declare -i count=0
  while true; do               
   if who | grep "^$username" &> /dev/null; then                          echo "$username is logged."                        
     break      
   else                     
     let count++                    
     echo "$count $username is not login."               
   fi               
   sleep 3         
   done#!/bin/bash      
#        
declare -i count=0        
username=$1
  if [ $# -lt 1 ]; then   #判断参数是否为空               
    echo "At lease one argument."                 
      exit 1           
  fi
  if ! id $username &> /dev/null; then                 
    echo "No such user."               
    exit 2           
  fi  until who | grep "^$username" &> /dev/null; do (条件作为循环条件)
  let count++  
          echo "$count $username is not login."  
                 sleep 3  
             done
  echo "$username is logged on."
  while循环的特殊用法:
  遍历文件的每一行:   
                while read VARIABLE; do     
                    循环体     
                done < /PATH/FROM/SOME_FILE   #后为重定向,提供给
  VARIBLE
  示例:找出UID为偶数的所有用户,显示其用户名和ID号;   

#!/bin/bash                     
#                     
while read line; do                        
     userid=$(echo $line | cut -d: -f3)                       
        if [ $[$userid%2] -eq 0 ]; then                                 echo $line | cut -d: -f1,3                        
        fi                     
done < /etc/passwd  #将/etc/passwd传给 line变量,从第一行开始操作)  for循环的特殊用法:   
            for ((expr1;expr2;expr3)); do     
                循环体     
            done
  expr1: 定义控制变量,并初始赋值;   
            expr2: 循环控制条件;     
                进入条件:控制条件为“真”     
                退出条件:控制条件为“假”     
            expr3: 修正控制变量
            示例:求100以内所有正整数之和;                   #!/bin/bash                     
#                     
declare -i sum=0
  for ((i=1;i<=100;i++)); do                        
     let sum+=$i                     
     done
   echo "Sum: $sum."  

  练习1:打印九九乘法表;
DSC00039.jpg DSC00040.jpg   
  练习2:传递一个文本文件为参数给脚本,取出此文件的所有的偶数行给予显示,行前要显示行号;

  cat –n 显示行号(包括空行)   -b显示行号(不包括行号)
  使用while循环语句,其中变量m用于判断行号,从1开始并计数,同时与2取模判断是否为偶数行,如果为
  偶数行采用变量 m 加上行输出,/etc/fstab文件作为 readline的输入
DSC00041.jpg

  第五: 函数:  
    函数即function: 功能  
把一段具有独立功能代码封装在一起,并给予命名;后续用到时,可直接通过给定函数名来调用整体代码;
  函数只有被调用才会执行,不调用的情况下不会执行。
  函数作用:  
           代码重用;  
           模块化编程;
  函数的使用方法:  
         先定义:编写函数代码  
        后调用:给出函数名,还可按需传递参数
  定义方法:  
        (1) function f_name {  
             函数体  
              }
  (2) f_name() {  
              函数体  
              }
  调用函数:  
    f_name [argu1, argu2, ...]   参数可选
  示例:创建函数countines,进行循环如果文件是普通文件
  -f(判断)则显示行数(这时调用countlines函数)
DSC00042.jpg

  函数调用$1 、$2等方法进行调用
  自定义函数状态返回值:   
            return [#]     
                0: 成功     
                1-255:失败
  注意:函数代码执行时,一旦遇到return,函数代码终止运行,函数返回;
  示例:此前的服务脚本  

#!/bin/bash        
#      
prog=$(basename $0)      
lockfile="/var/lock/subsys/$prog"      
#echo $lockfile
   if [ $# -lt 1 ]; then            
      echo "Usage: $prog start|stop|restart|status"            
      exit 1        
    fi
  start() {  #定义start函数              
     if [ -f $lockfile ]; then               
       echo "$prog is started yet."              
       else               
       touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."              
      fi                 }
   stop() {      #定义stop函数            
     if [ -f $lockfile ]; then               
       rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."       else               
       echo "$prog is stopped yet."            
     fi                 }
   restart() {    #定义restart函数            
      if [ -f $lockfile ]; then               
         rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."               else               
         touch $lockfile && echo "$prog is stopped, Starting $prog ok...."           fi                 }
   status() {     #定义status函数            
   if [ -f $lockfile ]; then              
      echo "Running..."            
        else              
      echo "Stopped..."            
   fi                 }
   case $1 in            
   start)               
        start   #调用start函数               
        ;;           
   stop)               
        stop   #调用stop函数                 
        ;;         
   restart)               
         restart   #调用restart函数                     
         ;;           
   status)                     
        status   #调用status函数                     
        ;;         
    *)         
        echo "Usage: $prog start|stop|restart|sttus"            
        exit 1        
        esac  

  示例:判断用户的ID号的奇偶性; (函数接受参数)  

#!/bin/bash                 
#                 
evenid() {   #定义函数                     
if [ $# -lt 1 ]; then   #判断参数个数是滞小于1,不为空                 return 1   #函数退出,后面代码不会执行                    fi
if ! id $1 &> /dev/null; then   #判断用户是否存在                    return 2                     
fi
userid=$(id -u $1)   #取出ID                    
     if [ $[$userid%2] -eq 0 ]; then   #判断userid的奇偶性                   echo "$1, Even user ID."                  
     else                        
       echo "$1, Odd user ID."                     
     fi                 }  以上函数定义完成
  evenid root
  evenid   
            echo $?  #echo作为输出数据
  evenid rooooooooooooot   
            echo $?
  #以上都在同一个脚本当中
   第六:模块化编程  
      功能:把脚本文件中的代码分隔为多段,放在不同的文件中     
                假设/root/bin/srv目录有两个文件:     
                (1) 函数文件  如示例start,restart、     
                (2) 脚本文件
  为脚本使用配置文件   
            一个文件中只定义变量     
            脚本文件source此变量定义的文件
  变量的作用域:   
            局部变量:     
                local VARIABLE=value
  示例:
DSC00043.jpg

  输出为
DSC00044.jpg

  存活时间:   
         函数执行开始,至函数返回结束;
  示例:
  functins定义文件
  包括Start,stop,restart,status,*等文件定义
  start() {     #定义start函数  
         if [ -f $lockfile ]; then  
             echo "$prog is started yet."  
         else  
           touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."  
          fi  
         }
  如下中. 脚本文件source此变量定义
DSC00045.jpg

  运行hisrv.sh文件,要求在一个目录下运行:调用./hisrv.sh start
DSC00046.jpg

  示例2:
  在一个同一目录创建username.conf文件内容如下:本文件中只定义变量
DSC00047.jpg

  在脚本中source此定义的文件,只需要修改username.conf文件变量
  脚本useradd.sh
  如果文件可读,利用.    source username.conf
DSC00048.jpg

  作业:上述关于bash编辑所有语法知识点和总结,要求图文并茂
  Part 2:作业部分
  作业5:写一个脚本:如果某路径不存在,则将其创建为目录;
  否则显示其存在,并显示内容类型
DSC00049.jpg

  作业6:
  写一个脚本,完成如下功能;判断给定的两个数值,孰大孰小;给定数值的方法:
  脚本参数,命令交互;(使用read,依然如此简单)
DSC00050.jpg

  作业7:求100以内所有奇数之和
  方法1: while循环
DSC00051.jpg

  方法2:until

  方法3:
DSC00052.jpg

  作业8:
  写一个脚本实现如下功能:
  (1) 传递两个文本文件路径给脚本;
  (2) 显示两个文件中空白行数较多的文件及其空白行的个数;
  (3) 显示两个文件中总行数较多的文件及其总行数;
  首先定义二个文件,分别为file1,file2,路径为/tmp/51cto/mkshell/
  脚本如下:用read –P 读取文件路径,四个条件分别赋值进行比较

  作业9:
  写一个脚本
  (1) 提示用户输入一个字符串;
  (2) 判断:
  如果输入的是quit,则退出脚本;
  否则,则显示其输入的字符串内容;

  作业:10:写一个脚本,打印2^n表;n等于一个用户输入的值;
  利用sum作为输出,输入数值作为for循环控制
DSC00053.jpg DSC00054.jpg

  作业11:写一个脚本,写这么几个函数:函数1、实现给定的两个数值的之和;函数2、
  取给定两个数值的最大公约数;函数3、取给定两个数值的最小公倍数;关于函数的选定、
  两个数值的大小都将通过交互式输入来提供。
gcd最大公约数    gbs最小公倍数=a*b/最大公约数  第一:创建脚本文件
  maxgcd用于计算最小公倍数时,调用gcd函数保存的变量
  三个函数分为按照1,2,3进行数字选择
DSC00055.jpg

  第二:功能函数:
  最大公约数利用until循环进行判断,首先判断是否第一个数字大于
  第二个数字,当第一个数字小于第二个数字时进行数字调换。
  然后利用until判断,当余数为0时退出循环,同时进行数字交换。
  计算完成将最大公约数赋值给maxgcd变量。
  当调用最大倍数时,调用gcd函数,取得maxgcd值。变将最大公
  公约数的输出到/dev/null中。同时根据最大公约数与最大公倍数的公式
  进行计算。
DSC00056.jpg

运维网声明 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.yunweiku.com/thread-478865-1-1.html 上篇帖子: Linux 学习:Linux特殊权限习题 下篇帖子: linux命令学习——strings
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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