linux学习

Shell 脚本编程基础

Shell介绍

  1. 什么是shell

    Shell是一个命令解释器,通常指的是/bin/bash,它在操作系统的最外层负责直接与用户对话,把用户的输入解释给操作系统,并且处理操作系统的输出结果,输出到屏幕给用户。这种对话方式可以是交互方式或者非交互式(脚本)的。

    image-20230814091108855

    可以通过/etc/shells文件查看当前系统所支持的Shell脚本种类:

    #查看shell脚本种类
    [root@www ~]# cat /etc/shells
    /bin/sh
    /bin/bash
    /usr/bin/sh
    /usr/bin/bash
    /usr/bin/tmux
    /bin/tmux
    /usr/bin/zsh
    /bin/zsh

    切换shell环境的方法

    #usermod命令:
    usermod -s /bin/bash 用户名
    #chsh命令:
    chsh -s /bin/bash 用户名
    #手动切换:
    [root@www ~]# /bin/sh
    sh-4.4# exit
    exit
    [root@www ~]# sh
    sh-4.4# exit
    exit
  2. 什么是Shell脚本

    当Linux命令或者语句不在命令行下执行,而是通过一个程序文件执行时,该程序就被称为shell脚本。用户在shell脚本中写入一系列的命令语句组合,并且将这些命令、变量和流程控制语句有机的组合在一起就形成了一个功能强大shell脚本。

  3. shell的执行方式

    交互式执行的命令:人工干预、智能化程度高、逐条解释执行、效率低

    非交互执行的脚本:需提前设置、智能化难度大、批量执行、效率高,方便写脚本后台运行

Shell脚本执行

  1. Shell脚本的建立

    在Linux中Shell脚本通常是在编辑器(vi/vim)中编写的,脚本的第一行会指出由哪一个解释器来执行脚本中的内容,比如:

    # !/bin/bash
    # 注释
    可执行命令

    脚本中开头的"#!"被称为幻数,在执行bash脚本时,内核会根据“#!”后的解释器来确定使用何种解释器来解释脚本的内容。

    运行:

    #第一种方式:指定脚本文件的路径,前提是由x权限
    [root@www ~]# vim first.sh
    #!/bin/bash
    #A test program for Shell-Script
    #仅仅用于输出打印 hello word
    echo "hello World! ^_^"
    [root@www ~]# chmod +x first.sh
    [root@www ~]# /root/first.sh
    hello World! ^_^
    #第二种方式:ssh 脚本文件路径
    [root@www ~]# sh /root/first.sh 
    hello World! ^_^
    #第三种方式:source 脚本文件路径
    [root@www ~]# source /root/first.sh 
    hello World! ^_^
    #第四种方式: . 脚本文件路径
    [root@www ~]# . /root/first.sh
    hello World! ^_^

    调试:

    # 第一种方式:直接观察执行中的输出、报错信息
    # 第二种方式:通过 sh -x 开启调试模式
    [root@www ~]# sh -x /root/first.sh 
    + echo 'hello World! ^_^'
    hello World! ^_^
    + ls /root/
    公共  下载             anaconda_s      etc1.txt      haha.tar.xz           
    + echo 执行结束
    执行结束
    #第三种方式: 通过 bash -x 开启调试模式
    [root@www ~]# bash -x first.sh 
    + echo 'hello World! ^_^'
    hello World! ^_^
    + ls /root/root
    ls: 无法访问'/root/root': 没有那个文件或目录
    + echo 执行结束
    执行结束
    #第四种方式: 在可能出错的地方设置echo
  2. shell变量

    变量的设置与取消

    定义/赋值变量

    • 变量名=变量值
    [root@www ~]# x=12
    [root@www ~]# var1=centos

    ​ 注意事项:

    1. 若指定的变量名已存在,相当于为此变量重新赋值
    2. 等号两边不要有空格
    3. 变量名由字母/数字/下划线组成,区分大小写
    4. 变量名不难以数字开头,不要使用关键字和特殊字符(如:+、-、!等)
    • 查看变量
    • 引用变量值:$变量名
    • 查看变量值 echo $变量名 、echo ${变量名}
    • [root@www ~]# echo $x
      12
      [root@www ~]# echo ${var1}
      centos
  • 取消变量
    • unset 变量名
    • 
      [root@www ~]# unset x
      [root@www ~]# echo $x

    [root@www ~]#

变量的种类

  • Shell变量分类

    • 环境变量
    • 变量名通常大写,由系统维护,用来设置工作环境,只有个别变量用户可以直接修改
    • 位置变量
    • bash内置。存储执行脚本时提供的参数
    • 预定义变量
    • bash内置。一类有特殊用途的变量。可直接调用。但不能直接赋值修改
    • 自定义变量
    • 由用户自主设置、修改及使用
  • 环境变量

    • 配置文件:/etc/profile 、~/.bash_profile
    • 相关操作
    • env:列出所有的环境变量
    • set:列出所有变量
    • 常见的环境变量
    • PWD :当前所在的工作目录
    • PATH :命令搜索路径
    • .........
  • 预定义变量

    • $0 当前所在进程或脚本名
    • $$ 当前运行进程的PID号
    • $? 命令执行后的返回状态,0表示正常,1或其他表示异常
    • $# 已加载的位置变量个数
    • $* 所有位置变量的值
    • $@ 所有位置变量的值
  • 位置变量

    • 在执行脚本时提供的命令行参数
    • 表示为$n,n为序号
    • $1、$2、.....${10}、.......
    [root@www ~]# vim /root/test.sh
    #!/bin/bash
    echo "脚本的名称为:$0"
    echo "第一个参数的名称为:$1"
    echo "第二个参数的名称为:$2"
    echo "第三个参数的名称为:$3"
    echo "第四个参数的名称为:$4"
    echo "第五个参数的名称为:$5"
    echo "第10个参数的名称为:${10}"
    [root@www ~]# chmod a+x test.sh 
    [root@www ~]# /root/test.sh 1 2 3 4 5 6 7 8 9 10
    脚本的名称为:/root/test.sh
    第一个参数的名称为:1
    第二个参数的名称为:2
    第三个参数的名称为:3
    第四个参数的名称为:4
    第五个参数的名称为:5
    第10个参数的名称为:10

变量值及范围控制

  • 扩展赋值操作

    # 双引号" " :运行扩展,以$引用其他变量
    [root@www ~]# echo "呵呵呵,你是$USER"
    呵呵呵,你是root
    
    # 单引号' '  :禁止扩展,即使$也视为普通变量
    [root@www ~]# echo '呵呵呵,你是$USER'
    呵呵呵,你是$USER、
    
    # 反撇号   :将命令的执行输出作为变量 ;$()与``等效,但$()更方便嵌套 [root@www yum.repos.d]# echo $a date [root@www yum.repos.d]# a=date [root@www yum.repos.d]# echo $a 2023年 08月 14日 星期一 14:48:24 CST [root@www yum.repos.d]# a=$(date) [root@www yum.repos.d]# echo $a 2023年 08月 14日 星期一 14:48:49 CST [root@www ~]# ls -l log-2023-08-14.tar.gz [root@www ~]# ls -l log-2023-08-14.tar.gz -rw-r--r-- 1 root root 1965203 8月 14 14:50 log-2023-08-14.tar.gz
  • read标准输入取值

    # 格式: read [-p "提示信息"] 变量名
    -p 提示信息
    [root@www ~]# read -p "请输入你的名字:" str
    请输入你的名字:zhangsan
    [root@www ~]# echo $str
    zhangsan
    -t 可指定超时秒数
    [root@www ~]# read -p "请输入你的名字:" -t 5 str
    请输入你的名字:
    [root@www ~]# echo $str
    
    [root@www ~]# 
    
    # 终端显示控制:
    stty -echo :关闭终端输出(无显示)
    stty echo:恢复终端输出(显示)
  • 变量作用范围

    • 局部变量:只在当前的shell环境有效,无法在子shell环境中使用
    [root@www ~]# school="hello word!"
    [root@www ~]# echo $school
    hello word!
    [root@www ~]# sh
    sh-4.4# echo $school
    
    sh-4.4# exit
    exit
    • 全局变量:在当前shell及子shell环境中均有效,使用export
    # export 局部变量名[=变量值] ... ... :为局部变量添加全局属性
    [root@www ~]# export school
    [root@www ~]# sh
    sh-4.4# echo $school
    hello word!
    sh-4.4# exit
    exit
    # export -n 全局变量名... ...:取消指定变量的属性

数值运算

  • 整数运算

    • 基本运算类别
    • shell同其他编程语言一样,支持多种运算符,其中算数运算符:+、-、*、/、%
      # 加法 +
      # 减法 -
      # 乘法 *
      # 除法 /
      # 求模 %
    • expr 运算工具
    类型 运算符 示例
    加法 + expr 43 + 45、expr $x + $y
    减法 - expr 43 - 45、expr $x - $y
    乘法 * expr 43 * 45、expr $x * $y
    除法 -/ expr 43 / 45、expr $x / $y
    取余数 -% expr 43 % 45、expr $x % $y

    注意:运算符与变量之间必须至少有一个空格;乘法操作应采用*转义,避免被shell视为通配符

    • $[]算式替换
    • 使用$[整数1 运算符 整数2]
    • 使用$((整数1 运算符 整数2))
    • 乘法操作*无需转义
    • 引用变量可省略$本身
    [root@www ~]# x=45
    [root@www ~]# echo $[x+21]
    66
    [root@www ~]# echo $((x+21))
    66
    • 变量的自增自减操作
    • 可使用命令$[]或let
    简写表达式 完整表达式
    i++ i=i+1
    i-- i=i-1
    i+=2 i=i+2
    i-=2 i=i-2
    i*=2 i=i*2
    i/=2 i=i/2
    i%=2 i=i%2
    [root@www ~]# i=1
    [root@www ~]# let i++
    [root@www ~]# echo $i
    2
    [root@www ~]# i=$[i+=1]
    [root@www ~]# echo $[i+=1]
    4

    注意:++i 与 i++ 同其他编程语言一样

  • 小数运算

    • 整数运算的局限性
    • Bash内仅支持整数运算,expr命令、$[] 算式替换不支持有小数运算
    [root@www ~]# expr 45 + 12.3
    expr: 非整数参数
    • 使用bc实现小数运算
    [root@www ~]# bc
    bc 1.07.1
    Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
    This is free software with ABSOLUTELY NO WARRANTY.
    For details type `warranty'. 
    1.2 + 2.3
    3.5
    100.23 - 45.23
    55.00
    quit
    
    # scale变量用来约束小数位,设置格式scale=n
    [root@www ~]# bc
    bc 1.07.1
    Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
    This is free software with ABSOLUTELY NO WARRANTY.
    For details type `warranty'. 
    scale=4
    12.34 * 45.23
    558.1382
    quit
    
    [root@www ~]# A=12.34
    [root@www ~]# echo "$A * 78.56" | bc
    969.43
    
    [root@www ~]# echo "scale=4;$A * 78.56;5/3" | bc
    969.4304
    1.6666
    
    [root@www ~]# result=$(echo "$A * 78.56" | bc)
    [root@www ~]# echo $result
    969.43
    [root@w
    • 小数值得比较
    • 基本用法:echo "数值1 比较符 数值2" | bc
    • 如果表达式成立。则返回结果为1,否则返回0
    • 常见操作:>、>=、<、<=、==、!=
    [root@www ~]# a=12.35
    [root@www ~]# b=45.2
    [root@www ~]# echo "$a == $b" | bc
    0
    [root@www ~]# echo "$a > $b" | bc
    0
    [root@www ~]# echo "$a < $b" | bc
    1

条件测试

  • 测试操作概述

    • Shell脚本的智能化
    • 为命令的执行提供最直接的识别依据
    • 文件或目录的读、写等状态
    • 数值大小
    • 字符串是否匹配
    • 多条件组合
    • test测试操作
    • test 选项 参数
    • [ 选项 参数 ] 注意:[ ] 与条件表达式之间需要至少一个空格进行分隔
  • 常见的操作测试

    • 字符串比较
    • 主要用法:[ 操作符 字符串 ] 或 [ 字符串1 操作符 字符串2 ]
    操作符 含义
    -z 字符串的值为空
    -n 字符串的值不为空
    == 两个字符串相同
    != 两个字符串不同
    # 示例:
    [root@www ~]# str=''
    [root@www ~]# [ -z $str ]
    [root@www ~]# echo $?
    0
    [root@www ~]# str='abc'
    [root@www ~]# [ -z $str ]
    [root@www ~]# echo $?
    1
    [root@www ~]# [ -n $str ]
    [root@www ~]# echo $?
    0
    [root@www ~]# str1='abc'
    [root@www ~]# str2='abc'
    [root@www ~]# [ $str1 == $str2 ]
    [root@www ~]# echo $?
    0
    [root@www ~]# [ $str1 != $str2 ]
    [root@www ~]# echo $?
    1
    • 整数值比较
    • 主要用法:[ 整数值1 操作符 整数值2 ]
    操作符 含义
    -eq 等于
    -ne 不等于
    -ge 大于或等于
    -le 小于或等于
    -gt 大于
    -lt 小于
    [root@www ~]# who
    root     pts/0        2023-08-14 14:43 (192.168.199.1)
    root     pts/1        2023-08-14 10:11 (192.168.199.1)
    [root@www ~]# who | wc -l
    2
    [root@www ~]# num=$(who | wc -l)
    [root@www ~]# [ $num -le 5 ] && echo "OK"
    OK
    [root@www ~]# [ $(who | wc -l) -le 5 ] && echo "OK"
    OK
    • 文件状态测试
    • 主要用法:[ 操作符 文件或目录 ]
    操作符 含义
    -e 判断对象是否存在,若存在则为真
    -d 判断对象是否为目录,若是则为真
    -f 判断对象是否为一般文件,若是则为真
    -r 判断对象是否有可读权限,若有则为真
    -w 判断对象是否有可写权限,若有则为真
    -x 判断对象是否有可执行权限,若有则为真
    [root@www ~]# [ -d /etc/hosts ]
    [root@www ~]# echo $?
    1
    [root@www ~]# [ -f /etc/hosts ]
    [root@www ~]# echo $?
    0
    [root@www ~]# [ -r /etc/hosts ]
    [root@www ~]# echo $?
    0
    [root@www ~]# [ -w /etc/hosts ]
    [root@www ~]# echo $?
    0
    [root@www ~]# [ -w /etc/hosts ] && echo "YES"
    YES
  • 组合多个条件

    • 逻辑分隔操作
    • 主要用法:命令1 操作符 命令2.......
    • [ 条件1 ] 操作符 [ 条件2 ]
    操作符 含义
    && 给定的条件都必须成立,整个结果为真
    || 只要其中一个条件为真,则结果为真
    • 条件组合应用
    [root@www ~]# [ $USER == "root" ] && [ $PWD == "/root" ]
    [root@www ~]# [ $? -eq 0 ] && echo "YES"
    YES
    
    [root@www ~]# [ -d "/opt/testdir" ] || mkdir -p /opt/testdir
    [root@www ~]# ls -ld /opt/testdir/
    drwxr-xr-x 2 root root 6 8月  14 16:57 /opt/testdir/

留言

您的邮箱地址不会被公开。 必填项已用 * 标注