码迷,mamicode.com
首页 > 系统相关 > 详细

20150913 Linux Shell

时间:2015-09-28 19:12:21      阅读:376      评论:0      收藏:0      [点我收藏+]

标签:程序开发   应用程序   后台运行   程序员   解释器   

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为空

        技术分享 

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   #导出后为环境变量

  技术分享 

分别进入三个bash子进程,使用echo $name

正常可以输出相关值obama

技术分享

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

技术分享

销毁:(手动、自动)
   unset name

第四、脚本:文本文件 
  运行脚本:事实上是运行一个bash进程,此进程负责从脚本文件中读取一个执行逻辑,

而后由bash进程负责解析并运行此逻辑;脚本作为参数提供bash运行。
1)启动脚本:

两种方式:
    (1) # bash /PATH/TO/SCRIPT_FILE     bash加路径
    (2) 一个执行权限, (单独运行)   # ./PATH/TO/SCRIPT_FILE

语法格式: 

   shebang语法:第一行顶格写) 
      #!/bin/bash   (解释器路径,运行下而脚本中内容)

    第一行:顶格给出shebang
    注释行:#

脚本示例:执行或者./shell名称(之前增加执行权限)

技术分享

  *备注:--stdin表示可以用任意文件做标准输入,这里是echo

其中第一个testuser1是为密码,后利用—stdin进行引用

2)bash的常用选项: 
    -n: 检查脚本中的语法错误; 
    -x:调试执行脚本;

    bash  脚本名称:直接运行

技术分享

3)命令状态结果: 
   bash进程用于追踪执行的命令成功与否的状态: 
      0: 成功 
      1-255:失败(其中1、2、127、63、64是bash内置其它可自定义)

   特殊变量: 
       $?:上一条命令的执行状态结果;

技术分享

  布尔型: 
     “真”:成功 
     “假”:失败

   自定义脚本的状态结果: 
       exit [n]

   注意:脚本中任何位置执行了exit命令即会终止当前shell进程;

技术分享

4)条件测试:  
  界定程序执行环境;

     (1) 根据运行的命令的状态结果; 根据结果$?返回值进行判断!结果成功或失败 
     (2) 测试表达式 
        test EXPRESSION    例如: 
        [ EXPRESSION ]   注意:[ ]内部前后二端有空格,无空格会提示语法  内建命令 
       [[ EXPRESSION ]]    同样需要空格,bshell关键字

  测试表达式常规包括以下三种:

    第一种:整数测试:双模操作符,隐含着做数值大小比较,所以不要给变量引用加引用

      $A -gt $B:是否大于;是则为“真”,否则为“假”;   A变量中的数值是否大于B变量的值

     技术分享 

返回非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":是否等于; 比较常用

   技术分享 
   "$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: 当前用户是否为指定文件的属组;

示例:

     技术分享

第五种:双目操作符: (二个操作符) 
    $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: 取反

  技术分享

  技术分享

上述示例中如果条件为假,则不运行后续”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时中{} 

  示例:判断输入的文件是否存在?如果存在则计算行数

如果不存在则输出不是文件

  技术分享

     运行利用shell名称  filename形式  ./file2.sh /etc/fstab

  ./file2.sh为脚本,/etc/fstab为变量$1的值

   技术分享

特殊变量:判断参数是输入  
        $?: 命令的状态结果;

       $0:表示脚本名称 
       $#: 传递给脚本或函数的参数的个数; 
      $*和$@: 引用传递给脚本或函数的参数列表;

  示例:$#用于判断./shell.sh文件后面是否输入参数

当空时输出Usage:./shell.sh <file>./shell.sh后面要有参数文件路径。

  exit 1条件不满足出退出当前shell脚本 

     当有路径参数时正常输出。

    技术分享

   shift [n]:轮替

      例如有三个参数   1,2,3,当启用该参数时,第一次用完后将参数1

替出,这时参数为2,3,原用参数前移一位。以此类推。

      示例如下:

     技术分享

         $*表示所有引用参数

         每次引用$1后,shift后后续变量前移。分别以A,B,C输出,

        $*输出最后一个C。shift 2 表示一次踢2个例如,一般用于

           循环环境中。

      技术分享

与用户交互:  
   read命令: read从输入中读取保存到指定变量当中

help read查看命令 
      read [options] VAR... 
          -p "PROMPT"    提示符 
          -t timeout   超时时间

 技术分享

   上面将文件路径分别保存到变量file1、 file2中

   在交互输入中包括二种状态

第一种情况:交互输入的值在于变量

   当给定的变量与输入不匹配时,自左至右分别赋值,

把剩余给最后一个变量 。示例如下:,将debug message给变量b

技术分享     

第二种情况 :变量值大于交换输入的值,后续的变量将不会赋值。

输出则为空。示例:变量a ,b 赋值,c为空

技术分享

     在交互前输入相关提示信息,read可利用-p选项  

echo –n  输入不换行

技术分享

技术分享

示例:

            #!/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)   变量赋值

         技术分享 

                 将结果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

  技术分享 
  (4) VARIABLE=$(expr $A + $B)       expr命令引用,引用后给变量

    技术分享

     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 ]]    必须在双括号中,同时=~ 二侧需要有空格

          判断左侧变量字符串与右则匹配

       技术分享

          . 表示单个字符,需要转译符\.    \.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有这个用户则输出用户

  技术分享

              if COMMAND1; then 
                   COMMAND2 
              fi

短路操作符:||    如果第一个为真,都为真,(或) 
          true || true = true 
          true || false = true

          false || true = true 
          false || false = false

  示例:如果每个用户不存在,添加一个新用户

技术分享

          if ! COMMAND1; then 
               COMMAND2 
           fi

示例:

技术分享

     如果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 读取文件路径,四个条件分别赋值进行比较

     技术分享

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

      技术分享

   练习:写一个脚本,打印九九乘法表;

       循环嵌套

    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以内所有偶数之和,以及所有奇数之和;

         技术分享
            练习2:实现九九乘法表;

         技术分享 技术分享
            练习3:分别使用while和until循环实现添加10个用户:user1-user10;

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

        技术分享 技术分享

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

       技术分享   技术分享

  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:打印九九乘法表;

 技术分享 技术分享 
  练习2:传递一个文本文件为参数给脚本,取出此文件的所有的偶数行给予显示,行前要显示行号;

    cat –n 显示行号(包括空行)   -b显示行号(不包括行号)

使用while循环语句,其中变量m用于判断行号,从1开始并计数,同时与2取模判断是否为偶数行,如果为

偶数行采用变量 m 加上行输出,/etc/fstab文件作为 readline的输入         

 技术分享

第五: 函数: 
    函数即function: 功能 
把一段具有独立功能代码封装在一起,并给予命名;后续用到时,可直接通过给定函数名来调用整体代码;

函数只有被调用才会执行,不调用的情况下不会执行。

     函数作用: 
           代码重用; 
           模块化编程;

    函数的使用方法: 
         先定义:编写函数代码 
        后调用:给出函数名,还可按需传递参数

    定义方法: 
        (1) function f_name { 
             函数体 
              }

       (2) f_name() { 
              函数体 
              }

    调用函数: 
    f_name [argu1, argu2, ...]   参数可选

示例:创建函数countines,进行循环如果文件是普通文件

-f(判断)则显示行数(这时调用countlines函数)

 技术分享

  函数调用$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

      示例:

          技术分享

                     输出为

         技术分享

            存活时间:
                函数执行开始,至函数返回结束;

    示例:

       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此变量定义

    技术分享

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

   技术分享

       示例2:

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

   技术分享

   在脚本中source此定义的文件,只需要修改username.conf文件变量

        脚本useradd.sh

      如果文件可读,利用.    source username.conf

  技术分享

作业:上述关于bash编辑所有语法知识点和总结,要求图文并茂

 

Part 2:作业部分

作业5:写一个脚本:如果某路径不存在,则将其创建为目录;

否则显示其存在,并显示内容类型

技术分享

作业6:

写一个脚本,完成如下功能;判断给定的两个数值,孰大孰小;给定数值的方法:

脚本参数,命令交互;(使用read,依然如此简单)

技术分享

作业7:求100以内所有奇数之和

    方法1: while循环

技术分享

    方法2:until

技术分享

    方法3:

技术分享

作业8:

写一个脚本实现如下功能:

(1) 传递两个文本文件路径给脚本;

(2) 显示两个文件中空白行数较多的文件及其空白行的个数;

(3) 显示两个文件中总行数较多的文件及其总行数;

首先定义二个文件,分别为file1,file2,路径为/tmp/51cto/mkshell/

          脚本如下:用read –P 读取文件路径,四个条件分别赋值进行比较

技术分享

 

作业9:

写一个脚本

(1) 提示用户输入一个字符串;

(2) 判断:

如果输入的是quit,则退出脚本;

否则,则显示其输入的字符串内容;

技术分享

作业:10:写一个脚本,打印2^n表;n等于一个用户输入的值;

   利用sum作为输出,输入数值作为for循环控制

技术分享技术分享

作业11:写一个脚本,写这么几个函数:函数1、实现给定的两个数值的之和;函数2、

取给定两个数值的最大公约数;函数3、取给定两个数值的最小公倍数;关于函数的选定、

两个数值的大小都将通过交互式输入来提供。

gcd最大公约数    gbs最小公倍数=a*b/最大公约数

  第一:创建脚本文件

     maxgcd用于计算最小公倍数时,调用gcd函数保存的变量

三个函数分为按照1,2,3进行数字选择

技术分享

第二:功能函数:

   最大公约数利用until循环进行判断,首先判断是否第一个数字大于

第二个数字,当第一个数字小于第二个数字时进行数字调换。

  然后利用until判断,当余数为0时退出循环,同时进行数字交换。

计算完成将最大公约数赋值给maxgcd变量。

  当调用最大倍数时,调用gcd函数,取得maxgcd值。变将最大公

公约数的输出到/dev/null中。同时根据最大公约数与最大公倍数的公式

进行计算。

技术分享

20150913 Linux Shell

标签:程序开发   应用程序   后台运行   程序员   解释器   

原文地址:http://wangsongbin.blog.51cto.com/1130001/1698862

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!