Shell
文章目录
- Shell
- 1. 简介
- 2. Shell 脚本入门
- 3. 变量
- 4. 运算式
- 5. 条件判断
- 6. 流程控制
- 6.1 if 判断
- 6.2 case 语句
- 6.3 for 循环
- 6.4 while 循环
 
- 7. read 读取控制台输入
- 8. 函数
- 8.1 系统函数
- 8.2 自定义函数
 
- 9. 正则表达式入门
- 10. 文本处理工具
- 10.1 cut
- 10.2 awk
 
- 11. 归档文件案例
1. 简介
Shell是一个命令行解释器,它接收应用程序/用户命令,然后调用操作系统内核。Shell还是一个功能相当强大的变成语言。
查看 Linux 提供的 Shell 解释器:cat /etc/shells ,其中 sh 是软链接,指向 bash ,CentOS 默认的解析器是 bash
2. Shell 脚本入门
脚本文件格式:#!/bin/bash 开头,表示指定解析器
脚本的执行方式:
- bash 脚本路径或- sh 脚本路径:这种方式不用赋予- x权限
- 脚本路径:当前目录下必须用- ./脚本名的方式执行,要求必须有- x权限
- .或- source:无需- x权限,且不会在当前 shell 中打开一个子 shell 来执行脚本内容。- 方式1和2会打开子 shell 执行脚本内容,执行结束再回到父 shell。
- 开子 shell 与不开子 shell 的区别就在于,环境变量的继承关系,如在子 shell 中设置的当前变量,父 shell 是不可见的
 
3. 变量
- 常用系统变量:$HOME、$PWD、$SHELL、$USER等
- 自定义变量:变量名=变量值,撤销变量:unset 变量名,静态变量:readonly 变量静态变量不能撤销。export 变量名提升为全局变量,变量名规则:- 环境变量名建议大写
- 变量默认都是字符串类型,无法直接进行数值运算
- 变量有空格需用单引号或双引号括起来
 
- 特殊变量: - $n:n 为数字,- $0代表该脚本名称,- $1-- $9代表第一到第九个参数,十以上的参数需要用大括号包含,如- ${10}
- $#:获取所有输入参数个数,常用于循环,判断参数的个数是否正确以及加强脚本的健壮性
- $*:这个变量代表命令行中所有的参数,- $*把所有的参数看成一个整体;当被双引号包含时,相当于把所有参数拼成了一个字符串
- $@:这个变量也代表命令行中所有的参数,不过- $@把每个参数区分对待;相当于把所有参数拼成一个集合,只有当被双引号包含时才与- $*有区别
- $?:最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确
 
4. 运算式
通过 $((运算式)) 或 $[运算式] 可以获取并接收一个运算式的值
[linux@CentOS01 ~]$ a=$[1+2+3]
[linux@CentOS01 ~]$ echo $a
6
5. 条件判断
基本语法:
- test condition
- [ condition ],condition 前后必须有空格
常用判断条件:
- 比较 :下面是整数间的比较,如果是字符串之间的比较 ,用等号 =判断相等;用!=判断不等
| 符号 | 含义 | 
|---|---|
| -eq | 等于(equal) | 
| -ne | 不等于(not equal) | 
| -lt | 小于(less than) | 
| -le | 小于等于(less equal) | 
| -gt | 大于(greater than) | 
| -ge | 大于等于(greater equal) | 
- 文件权限判断:[ -r hello.txt ]判断hello.txt有没有读权限
- 文件类型判断:-e文件存在;-f文件存在并且是常规文件;-d文件存在并且是一个目录
一般可以直接用 $? 来表示上一条条件判断结果,false 为 0,true 为 1;
还可以用 && 或 || 来控制多条件判断及语句执行,&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令
6. 流程控制
6.1 if 判断
- 单分支
if [ 条件判断式 ];then程序
fi
或者
if [条件判断式]
then程序
fi
- 多分支
if [ 条件判断式 ]
then程序
elif [ 条件判断式 ]
then程序
else程序
fi
6.2 case 语句
case $变量名 in
"值1")变量值等于值1时执行的程序
;;
"值2")变量值等于值2时执行的程序
;;
"*")变量值都不是上述值执行的程序
;;
esac
6.3 for 循环
语法1:
for (( 初始值;循环控制条件;变量变化 ))
do程序
done
语法2:
for 变量 in 值1 值2 值3...
do程序
done
6.4 while 循环
while [ 条件判断式 ]
do程序
done
7. read 读取控制台输入
基本语法:read (选项) (参数)
- 选项: - -p:指定读取值时的提示符
- -t:指定读取值时等待的时间(秒)如果-t 不加表示一直等待
 
- 参数:指定读取值的变量名
8. 函数
8.1 系统函数
- basename [string / pathname] [suffix]:取路径里的文件名称,指定了- suffix会将对应- suffix去掉
- dirname 文件绝对路径:取文件路径的绝对路径目录,不含文件名
8.2 自定义函数
基本语法:
[function] funcName[()]
{Action;[return int;]
}
如
function sum()
{s=0;s=$[$1+$2]echo "$s";
}
经验技巧:
- 必须在调用函数地方之前,先声明函数
- 函数返回值,只能通过 $?系统变量获得,如果不加return返回,将以最后一条命令运行结果;如用return,后跟数值 n(0-255)
9. 正则表达式入门
正则表达式使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。在 Linux 中,grep,sed,awk 等文本处理工具都支持通过正则表达式进行模式匹配
常规匹配:cat a.txt | grep abc 就会匹配所有包含 abc 的行
常用特殊字符
- ^:匹配一行的开头,- cat a.txt | grep ^a匹配所有 a 开头的行
- $:匹配一行的结束,- cat a.txt | grep a$匹配所有 a 结尾的行
- .:匹配一个任意字符,- cat a.txt | grep a.b匹配 aab 、abb 、acb … 的所有行
- *:不单独使用,和上一个字符连用,表示匹配上一个字符0次或多次
- \:转义字符,如- cat a.txt | grep \$匹配包含 $ 的行
字符区间:[]
- [6,8]:匹配6或者8
- [6-8]:匹配一个 6-8 间的数字
- [0-9]*:匹配任意长度的数字字符串3
- [a-z]:匹配一个 a-z 间的字符
- [a-c,e-f]:匹配一个 a-c 或者 e-f 间的字符
10. 文本处理工具
10.1 cut
cut [选项参数] filename :默认分割符是 \t
| 选项参数 | 功能 | 
|---|---|
| -f | 列号,提取第几列,可用 ,隔开表示多列 | 
| -d | 分隔符,按照指定分隔符分割列,默认是制表符 \t | 
| -c | 按字符进行切割后加 n 表示取第几列,如 -c 1 | 
切割 ifconfig 后打印的 IP 地址:
[linux@CentOS01 ~]$ ifconfig ens33 | grep netmask | cut -d " " -f 10
192.168.115.128
10.2 awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理
基本语法:awk [选项参数] ‘/pattern1/{action1} /pattern2/{action2}...’ filename
- pattern:表示 awk 在数据中查找的内容,就是匹配模式
- action:在找到匹配内容时所执行的一系列命令
| 选项参数 | 功能 | 
|---|---|
| -F | 指定输入文件分隔符 | 
| -v | 赋值一个用户定义变量 | 
内置变量:
| 变量 | 说明 | 
|---|---|
| FILENAME | 文件名 | 
| NR | 已读的记录数(行号) | 
| NF | 浏览记录的域的个数(切割后,列的个数) | 
切割 ifconfig 后打印的 IP 地址:
[linux@CentOS01 ~]$ ifconfig ens33 | awk '/netmask/ {print $2}'
192.168.115.128
11. 归档文件案例
实现一个当天对指定目录归档备份的脚本,输入一个目录名称(末尾不带/),将目录下所有文件按天归档保存,并将归档日期附加在归档文件名上,放在 /root/archive 下。
这里用到了归档命令:tar ,后面可以加上 -c 选项表示归档,加上 -z 选项表示同时进行压缩,得到的文件后缀名为 .tar.gz 。如需每天执行可结合 crond 服务使用。
脚本实现如下:
#!/bin/bash
# 首先判断输入参数个数是否为 1
if [ $# -ne 1 ]
thenecho "参数个数错误!应该输入一个参数,作为归档目录名"exit
fi# 从参数中获取目录名称
if [ -d $1 ]
thenecho
elseechoecho "目录不存在!"echoexit
fiDIR_NAME=$(basename $1)
DIR_PATH=$(cd $(dirname $1); pwd)
# 获取当前日期
DATE=$(date +%y%m%d)# 定义生成的归档文件名称
FILE=archive_${DIR_NAME}_$DATE.tar.gz
DEST=/root/archive/$FILE# 开始归档目录文件
echo "开始归档..."
echotar -czf $DEST $DIR_PATH/$DIR_NAMEif [ $? -eq 0 ]
thenechoecho "归档成功!"echo "归档文件为:$DEST"echo
elseecho "归档出现问题!"echo
fiexit