什么是Shell

在Linux操作系统中,有两个非常重要的工具:①Linux命令;②Shell。Linux命令是Linux系统对用户提供的众多系统功能接口,每一个Linux命令都能完成一个独立的系统功能;Shell是一个基于C语言开发的应用程序,它可以通过各种逻辑语法和程序控制指令把一系列的Linux命令组合在一起,形成一个面向过程的程序命令(Shell Script)。

Linux命令一般需要在特定环境中执行,我们一般的Linux命令就是在Shell中执行的,需要特定的环境变量等支持;而Shell脚本会fork一个子进程去执行,如果在脚本中涉及环境变量的改变则只会改变子进程的环境,对Shell的环境变量没有影响。

我们知道Linux的Shell是一个组合并执行Linux命令的应用程序,所以Shell的实现并不只有一种,我们常用的Shell类型包括:sh、C Shell、TCSH、bash。Linux中默认的Shell为bash,一般保存在/bin/bash

也就是说,Linux命令是系统提供的具备各种不同功能的命令集合、Shell是一个可以将多个Linux命令组合为Shell脚本的应用程序,相当于一个脚本解析器。

Shell脚本基础_第1张图片


Shell脚本语法

  1. 在Linux中l脚本的第一行一般会向系统声明该脚本所使用的解析程序:

    #!/bin/bash,通过这条语句声明该脚本使用/bin/bash这个应用程序解析

  2. Shell脚本的基本表达式:

    表达式 功能
    ++、-- 自增、自减(与C语言的前后自增自减相同)
    +、-、*、/、% 加、减、乘、除、余运算
    ** 幂运算
    >、>=、<、<=、==、!= 比较运算
    <<、>> 按位左移、右移运算
    &、|、^ 与、或、异或运算
    &&、||、! 逻辑与、或、非
    exp?a:b 三目运算符
    #内容 单行注释
    :< 代表多行注释(EOF可以使用单引号、感叹号代替)
  3. 变量赋值:

    如何给变量赋值?如何调用变量?
    Shell的变量使用等于号赋值,且等号之间不允许有空格,必须要直接与等号相连v1="value"
    调用变量只需要将变量名连接在美元符号$后面v2=$v1,也可以使用大括号区分每个变量的边界v3=${v1}isgood

      #直接进行变量赋值
      a=12      #默认是字符串类型的"12",进行数值运算时会解析为数值型的12
      b=str1        #默认是字符串类型的"str1"
    
      #使用单引号和双引号进行变量赋值,双引号会解析变量、转义字符、反引号命令;而单引号则不会解析任何上面的东西,完全按照字符串字面值赋值。
      v="$a"    #这时变量v的值为12
      v='$a'    #这时变量v的值为'$a'
    
      #列表变量的赋值
      list=(v1,v2,v3)   #括号内为列表内容,中间使用空格分隔
      echo ${list[@]}   #通过${}来调用列表,[]内表示索引,[@]表示列表内的每一项

    注意使用以上方式的变量赋值,是无法进行任何命令以及运算的!,只能将变量解析出来,但是无法进行命令执行和数学运算。

      a=1
      b=2
      c="$a+$b"     #c的值为"1+2"而不是3
      d="ls -al"        #d的值为"ls -al"而不会执行
  4. 代换和Shell中的括号

    • 文件名代换

      简单地说就是一种可以使用在文件名上的通配符:

      *    #表示匹配任意多个任意字符
      ?    #表示匹配一个任意字符
      []   #表示匹配中括号内任意一个字符的第一次出现
      
      cd ./test[123abc]        #匹配test1、test2、test3、testa...
    • 命令代换,单括号

      单括号符功能:①命令组功能,可以执行单引号中的多个命令;②命令代换,在变量中的命令会执行并正常输出到标准输出中;③初始化Shell列表变量
      注意区分变量环境和非变量的环境,只有变量的环境下需要在单括号外加美元符号

       #在变量中使用反引号或单括号,可以将变量解析为shell命令并执行:
       a=`ls -al` #反引号可以进行命令代换
       b=$(ls -al)    #美元括号的内容会进行命令代换
      
       (pwd)  #执行pwd命令
       `pwd`  #执行pwd命令
    • 运算代换,双括号

      双括号符功能:①数值运算功能,只要内符合C语言运算语法,即可进行数值运算;②运算代换,在变量中的数值运算会正常进行后再进行赋值;③for语句功能,双括号可以在for循环中使用;
      注意区分变量环境和非变量环境,只有变量环境下需要在双括号外加美元符号

       #在变量中使用双引号,可以将变量解析为数值运算并执行:
       a=10
       b=$(($a+20))   #b的值为30
    • 中括号

      中括号功能:①Shell的内部命令,可用于进行条件测试返回True、False,等同于test命令;②正则表达式和通配符可以使用;③作为列表的索引使用

      要注意,作为条件测试的中括号是一个命令语句而不是一个符号。作为命令前中括号后需要带一个空格才能接参数,而后中括号就是作为该条件测试命令的最后一个参数,代表参数输入结束。前后中括号中间的值都作为命令的参数。
      并且作为一个命令,[在对开空格的字符串作处理时会发生问题。

       #if使用中括号条件测试,结果为输出yes
       if [ 10 -lt 20 ] && [ 1 -lt 2 ]    #此处前中括号后和后中括号前都需要加一个空格
       then
          echo yes
       else
          echo no
       fi
      
       #这里$name会解析为三个字符串,导致[命令参数错误
       name="here and there"
       if [ -n $name ]    #使用[ -n "$name" ]才能正常
       then
          echo "not empty"
       fi
       #这里的结果会报错  bash: [: too many arguments
    • 双中括号

      双中括号功能:①bash的内部关键字,能完成[的加强版功能,并且因为[[不是命令而是关键字,所以对参数的解析规则会略有不同。且与[每次只能做一种判断不停,[[可以使用&&、||等运算符,可以同时做多种比较。

        #if使用中括号条件测试,结果为输出yes
       if [[ 10 -lt 20 && 1 -lt 2 ]]  #此处前中括号后和后中括号前都需要加一个空格
       then
          echo yes
       else
          echo no
       fi
      
       #因为对参数的处理不同,可以直接处理带空格的字符串
       name="this is a test"
       if [[ -n $name ]]
       then
          echo "not empty"
       fi
       #结果会正常显示
    • 大括号

      大括号功能:①可以对文件名做扩展,作用类似通配符;②执行代码块,就是C中的代码块,每条命令结束都要加分号;③分隔变量名称和使用列表变量

       touch test{1..5}.txt   #会创建5个文件,其实就是通配符嘛
      
       a="${this}IsATest" #不使用大括号变量名会粘在一起
       a="${list[@]}"     #选择列表所有元素
  5. Shell中的特殊字符

    Shell中的字符都有许多特殊的用法:

    特殊字符 功能
    ; 分号,表示连续执行命令
    exp & 句尾的&号,表示命令在后台执行
    n&>file 重定向,将文件符n重定向到目标文件
    exp1 && exp2 两个命令中间的&&,表示exp1返回0才会执行exp2
    exp1 || exp2 两个命令中间的||,表示exp1返回非0才会执行exp2
    ${#var} 返回列表或变量的长度
    $0、$1、$2 和运行脚本的命令有关。0表示该脚本文件;1、2分别表示第1、2个参数
    $*、$@、$# 和运行脚本的命令有关。*和@表示参数列表;#表示参数个数
    $$、$? 和运行脚本的命令有关。\$表示脚本运行PID;?表示脚本退出码

Shell流程控制

  1. if语句

      #可以写成正常形式
      if condition1
      then
        cmd1
      elif condition2
      then
        cmd2
      else 
        cmd3
      fi
    
      #也可以写成一句话形式,中间用分号连接
      if condition1; then cmd1; elif condition2; then cmd2; else cmd3; fi
  2. for语句

      #正常形式
      for var in ${list[@]}
      do
        cmd1
        cmd2
        cmd3
      done
    
      #一句话形式,中间用分号分隔
      for var in ${list[@]}; do cmd1; cmd2; cmd3; done
  3. while语句

    while语句是先判断条件再执行循环,且条件为False时结束循环,同C语言

      #正常形式
      while condition
      do
        cmd1
        cmd2
      done
    
      #一句话形式,中间用分号分隔
      while condition; do cmd1; cmd2; done
  4. until语句

    until语句是执行函数后再判断条件,且条件为True时结束循环,同C语言

      until condition
      do 
        cmd1
        cmd2
      done
    
      until condition; do cmd1; cmd2; done
  5. case语句

      a=2
      case $a in
      1)
        cmd1
        ;;
      2)
        cmd2
        ;;
      *)
        cmd3
        ;;
      esac
    
      #一句话形式
      a=2
      case $a in 1) cmd1;; 2) cmd2;; *) cmd3;; esac
  6. 跳出循环

    可以在循环语句for、while、until以及枚举语句case中,使用break终止整个流程;使用continue跳过本次流程。此处与C语言相同。


Shell函数

Shell可以定义函数,之后可以随意调用。

funName(){  #定义函数,后面不用带参数,传参方法和命令相似
    (ls -al $1)
    echo $2

    i=$3
    while [ $i -gt 0 ]
    do
        echo $i
        i=$(($i-1))
    done
}

funName /usr this 3 #调用函数,后面是参数

新手发文,欢迎大佬指正错误