shell 脚本

一、基础概念

  • Shell 脚本

    Shell 脚本(shell script),是一种为 shell 编写的脚本程序。
    业界所说的 shell 通常都是指 shell 脚本,但读者朋友要知道,shell 和 shell script 是两个不同的概念。
    由于习惯的原因,简洁起见,本文出现的 "shell编程" 都是指 shell 脚本编程,不是指开发 shell 自身。
  • shell 环境

    Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了
    
    本教程关注的是 Bash,也就是 Bourne Again Shell,由于易用和免费,Bash 在日常工作中被广泛使用。同时,Bash 也是大多数Linux 系统默认的 Shell。
    在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为 #!/bin/bash。
    #! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。
  • 第一个shell脚本

    打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 test.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行,如果你用 php 写 shell 脚本,扩展名就用 php   好了。
    输入一些代码,第一行一般是这样:
    实例
    #!/bin/bash
    echo "Hello World !"
    #! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
    echo 命令用于向窗口输出文本。
  • 运行shell 脚本的两种方法:

    • 1.作为可执行程序
      将上面的代码保存为 test.sh,并 cd 到相应目录:
      chmod +x ./test.sh  #使脚本具有执行权限
      ./test.sh  #执行脚本
      注意,一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,
      而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找
    • 2.作为解释器参数
      直接运行解释器,其参数就是 shell 脚本的文件名,如:
      /bin/sh test.sh
      /bin/php test.php
      
      这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用

二、Shell 变量

  • 定义变量时,变量名不加美元符号($,PHP语言中变量需要):

    your_name="runoob.com"
    * 注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:
        1)命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
        2)中间不能有空格,可以使用下划线(_)
        3)不能使用标点符号
        4)不能使用bash里的关键字(可用help命令查看保留关键字)
    * 无效的变量命名
        ?var=123
        user*name=runoob
  • 除了显式地直接赋值,还可以用语句给变量赋值,如:

    for file in `ls /etc`
    或
    for file in $(ls /etc)
    
    以上语句将 /etc 下目录的文件名循环出来
  • 使用变量

    your_name="qinjx"
    echo $your_name
    echo ${your_name}
    • 变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:
      for skill in Ada Coffe Action Java; do
          echo "I am good at ${skill}Script"
      done
      
      推荐给所有变量加上花括号,这是个好的编程习惯。
    • 已定义的变量,可以被重新定义,如:
      your_name="tom"
      echo $your_name
      your_name="alibaba"
      echo $your_name
    • 只读变量: 使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变
    • 删除变量: 使用 unset 命令可以删除变量 ,unset 命令不能删除只读变量
    • 变量类型: 运行shell时,会同时存在三种变量
      1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量
      2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量
      3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
    • 使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
  • Shell 字符串

    字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号
    • 5)提取子字符串
      string="runoob is a great site"
      echo ${string:1:4} # 输出 unoo
    • 1)单引号
      str='this is a string'
      单引号字符串的限制:
        单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
        单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
    • 2)双引号
      your_name='runoob'
      str="Hello, I know you are \"$your_name\"! \n"
      echo -e $str
      
      输出结果为:Hello, I know you are "runoob"! 
      
      双引号的优点:
        双引号里可以有变量
        双引号里可以出现转义字符
    • 4)获取字符串长度
         string="abcd"     echo ${#string} #输出 4    
  1. 拼接字符串

Shell 数组

  • 定义数组
  • 读取数组
  • 获取数组的长度

Shell 注释

  • 单行注释: 以 # 开头的行就是注释,会被解释器忽略
  • 多行注释:
    :<<EOF
    注释内容...
    注释内容...
    注释内容...
    EOF
    使用其他符号:
    :<<'
    注释内容...
    注释内容...
    注释内容...
    '
    
    :<<!
    注释内容...
    注释内容...
    注释内容...
    !

Shell 传递参数

Shell 数组

Shell 运算符

  • 算术运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符

Shell echo 命令

Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出。命令格式:echo string

  • 1.显示普通字符串:
    echo "It is a test"
    这里的双引号完全可以省略,以下命令与上面实例效果一致:
    echo It is a test
  • 2.显示转义字符
    echo "\"It is a test\""
    结果将是:
    "It is a test"
  • 3.显示变量
    read name 
    echo "$name It is a test"
  • 4.显示换行
    echo -e "OK! \n" # -e 开启转义
    echo "It is a test"
  • 5.显示不换行
  • 6.显示结果定向至文件
    echo "It is a test" > myfile
  • 7.原样输出字符串,不进行转义或取变量(用单引号)
    echo '$name\"'
  • 8.显示命令执行结果
    echo `date`
    注意: 这里使用的是反引号 `, 而不是单引号 '

shell printf 命令

Shell test 命令

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

  • 数值测试

    num1=100
    num2=100
    if test $[num1] -eq $[num2]
    then
        echo '两个数相等!'
    else
        echo '两个数不相等!'
    fi
  • 字符串测试

    num1="ru1noob"
    num2="runoob"
    if test $num1 = $num2
    then
        echo '两个字符串相等!'
    else
        echo '两个字符串不相等!'
    fi
  • 文件测试

    -e 文件名如果文件存在则为真
    -r 文件名如果文件存在且可读则为真
    -w 文件名如果文件存在且可写则为真
    -x 文件名如果文件存在且可执行则为真
    -s 文件名如果文件存在且至少有一个字符则为真
    -d 文件名如果文件存在且为目录则为真
    -f 文件名如果文件存在且为普通文件则为真
    -c 文件名如果文件存在且为字符型特殊文件则为真
    -b 文件名如果文件存在且为块特殊文件则为真
    cd /bin
    if test -e ./bash
    then
        echo '文件已存在!'
    else
        echo '文件不存在!'
    fi

Shell 流程控制

  • if else

    • fi
    • if else
    • if else-if else 语法格式:
      if condition1
      then
          command1
      elif condition2 
      then 
          command2
      else
          commandN
      fi
  • for 循环
    for循环一般格式为:

    for var in item1 item2 ... itemN
    do
        command1
        command2
        ...
        commandN
    done
  • while 语句
    while 循环用于不断执行一系列命令,也用于从输入文件中读取数据。其语法格式为:

    while condition
    do
        command
    done
  • until 循环

  • case ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,是一种多分枝选择结构

  • 跳出循环
    在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell使用两个命令来实现该功能:break和continue。

break命令
break命令允许跳出所有循环(终止执行后面的所有循环)

continue
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环

Shell 函数

shell 可以用户定义函数,然后在shell脚本中可以随便调用。
shell中函数的定义格式如下:

[ function ] funname [()]
{
    action;
    [return int;]
}

shell 输入、输出重定向

shell 文件包含