8.11 Shell编程
• Shell脚本三个执行方式:
▪ ./hello.sh:需要授权,进程隔离(开启子进程)
▪ sh hello.sh:不需授权,进程隔离(开启子进程)
▪ source hello.sh:不需授权,进程不隔离(不开启子进程)
▶ 变量
• 变量定义:变量名=值 #注意!等号两边不能有空格!
▪ 定义字符串:name="Alice"
▪ 定义数字:age=25
▪ 定义命令执行结果:files=$(ls)
• 变量名规则:
▪ 只能包含字母、数字和下划线
▪ 不能以数字开头
▪ 严格区分大小写
▪ 避免使用Shell关键字
• 变量的使用
▪ 引用变量
在变量名前加$或${} 后者更加推荐(避免歧义)
▪ 变量默认值
如果变量未定义,提供默认值:
${变量名:-默认值} #变量为空或未定义时使用默认值
${变量名:=默认值} #变量为空时设置默认值并赋值
▪ 变量的作用域
局部变量:只能局部使用
全局变量:全局可用
函数变量:只能函数使用
子进程的变量:父进程使用不了
▪ 特殊变量
$0:当前脚本名
$1,$2..:脚本的参数
$#:参数的个数
$?:上一条命令的执行状态(0表示执行成功)
$$:当前Shell的进程ID
$*:所有参数(作为一个字符串)
$@:所有参数(作为多个字符串)
• 变量的操作:
▪ 字符串操作:
获取长度:${#变量名}
截取子串:${变量名:起始位置:长度}
替换第一个匹配:${变量名/旧字符串/新字符串}
替换所有匹配:${变量名//旧字符串/新字符串}
▪ fruits=("apple" "banana" "cherry") #定义数组
echo ${fruits[0]} 输出apple(索引从0开始)
echo ${fruits[@]} 输出所有元素
echo ${#fruits[@]} 输出数组长度
▶ 注意事项
• 等号两边不能有空格
name = "Alice" 错误
• 字符串建议加引号
• 避免未定义的变量
使用${变量:-默认值},防止脚本因变量未定义而报错
• 变量名避免特殊字符
• 脚本执行时,让用户自己输入:
read -p "请输入:" 变量名
• 基本条件判断结构
▪ if 条件1;then
代码块
elseif 条件2;then
代码块
else
代码块
fi
▪ case 变量 in
模式1)
代码块
;;
模式2)
代码块
;;
*)
默认情况
;;
esac
• 条件测试方式:
▪ 文件测试:
-e:文件是否存在 -f:是否是普通文件
-d:是否是目录 -r:是否可读
-w:是否可写 -x:是否可执行
-s:文件大小是否>0 -L:是否是符号链接
▪ 字符串比较:
"$str1" = "$str2" 字符串相等
"$str1" != "$str2" 字符串不相等
-z "$str" 字符串是否为空
-n "$str" 字符串是否非空
[[ "$str" == *模式* ]] 模式匹配(支持通配符)
字符串裁剪:
# 是左边开剪,% 是右边开剪。
语法| 方向| 匹配方式| 示例(path="/a/b/c")
---|---|---|---
${path#/}| 左侧| 最短| 删除第一个 / → a/b/c
${path##*/}| 左侧| 最长| 删除最后一个 / 及左侧 → c
${path%/}| 右侧| 最短| 删除末尾 /(若无则不删)→ /a/b/c
${path%%/*}| 右侧| 最长| 删除第一个 / 及右侧 → (空字符串)
▪ 数字比较:
-eq:等于 -ne:不等于 -gt:大于
-lt:小于 -ge:大于等于 -le:小于等于
▪ 逻辑运算:
&& 逻辑与 || 逻辑或 ! 逻辑非
▶ 循环:
• while循环
读取文件内容:
while read -r NAME PASSWD;do
循环体
done <users.txt
tips:按行读取文件中每一列字段给变量,变量必须按顺序占位
若文件有三列,NAME中储存第一列,PASSWD中储存后续所有列
while IFS=',' read -r name age:修改读取时的分隔符,默认空格
▪ read -n 1:输入任意一个字符,不用按回车,直接执行(完成了“按任意键继续……”的功能)
• for循环
▪ for i in {1..5} #循环1到5
▪ for i in {1..10..2} #循环1到10,步长为2
▪ for file in /home/* #遍历/home目录下的所有文件
▪ for color in "${colors[@]}" #遍历数组
▶ 函数
• 函数的定义:
▪ function 函数名 {
命令序列
}
▪ 函数名() {
命令序列
}
• 在其他文件中使用脚本文件中定义的函数
例:nginx.sh脚本文件中定义了函数nginx_fun()
在httpd.sh脚本文件中写:source ./nginx.sh引入脚本中所有函数
在httpd.sh中使用函数:nginx_fun
▶ 拓展
• 循环中如果执行命令过多,可以用{ }&把循环体代码括起来,把代码块当成一个整体放到后台运行,执行速度会变快(实现了并发性)
• 源码安装的三部曲:
第一步:配置(./configure)
第二步:编译(make)make -j4:使用4个内核编译,速度更快
第三步:安装(make install)
• [[ ]]和[ ]的区别:
[[]]| []
---|---
字符串比较==/!=| 字符串比较=/!=
&&与 ||或| -a与 -o或
支持通配符| 不支持通配符
变量可不加引号| 变量必须加引号
支持算术比较| 不支持算数比较