Shell 脚本编程基础
Shell介绍
-
什么是shell
Shell是一个命令解释器,通常指的是/bin/bash,它在操作系统的最外层负责直接与用户对话,把用户的输入解释给操作系统,并且处理操作系统的输出结果,输出到屏幕给用户。这种对话方式可以是交互方式或者非交互式(脚本)的。
可以通过/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
-
什么是Shell脚本
当Linux命令或者语句不在命令行下执行,而是通过一个程序文件执行时,该程序就被称为shell脚本。用户在shell脚本中写入一系列的命令语句组合,并且将这些命令、变量和流程控制语句有机的组合在一起就形成了一个功能强大shell脚本。
-
shell的执行方式
交互式执行的命令:人工干预、智能化程度高、逐条解释执行、效率低
非交互执行的脚本:需提前设置、智能化难度大、批量执行、效率高,方便写脚本后台运行
Shell脚本执行
-
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
-
shell变量
变量的设置与取消
定义/赋值变量
- 变量名=变量值
[root@www ~]# x=12 [root@www ~]# var1=centos
注意事项:
- 若指定的变量名已存在,相当于为此变量重新赋值
- 等号两边不要有空格
- 变量名由字母/数字/下划线组成,区分大小写
- 变量名不难以数字开头,不要使用关键字和特殊字符(如:+、-、!等)
- 查看变量
- 引用变量值:$变量名
- 查看变量值 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、 # 反撇号
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/