写在前面
本文介绍了关于linux Shell脚本的相关知识,其需要一定的linux基础,小白可以参考linux 快速入门这篇文章,有了linux基础才能更好理解本文,大佬随意。
Shell 快速入门
什么是Shell
Shell 是命令行解释器,它能够接受程序或用户命令,然后调用操作系统内核执行该命令,最后将命令返回给用户。
注意:
shell
是命令行解释器的统称,并不是一个具体的命令行解释器,linux中具体的解释器默认是bash
shell 脚本
shell 脚本
,通俗地可以理解为一个自定义的命令行,linux
执行了该命令行,就会完成一些用户自定义的操作(在Shell当中,空格表示隔断,因此不能随意地打空格)
shell 脚本的编写
Shell
脚本文件的后缀名为.sh
,且文件开头 第一行必须是#!/bin/bash
,以此表明该脚本的具体命令行解释器是什么,方便其他人使用(约定俗成的规矩)
除了上面约定俗成的规矩以外,
shell脚本文件
需要书写的内容全是linux
相关的基础命令(直接写)
shell 脚本的执行
脚本执行有两种方法
- 方法一:
sh + 脚本文件的相对路径
或者bash + 脚本文件的相对路径
- 方法二: 给对应的脚本文件(.sh)添加执行权限
chmod +x 脚本.sh
此时,只需要输入脚本文件的所在路径就可以运行了
修改脚本路径
每次我们执行自定义的脚本时,总是要依赖其路径来执行,那么我们能不能像执行普通的linux命令
(linux命令本质就是脚本)一样,在任何目录下都可以直接执行呢?答案是可以的,我们可以通过修改脚本路径来实现。
- 进入 ~目录 当中,用vim 打开.bashrc文件 输入命令
vim ./.bashrc
2.在文件末尾添加上以下命令,其中~/桌面/my_shell
为自定义脚本文件所在的目录(用户自定义)
- 输入以下命令
source ~/.bashrc
或者重新打开终端,至此,自定义脚本便可以在任意目录下直接调用(只需要输入脚本文件的文件名)
注意: 以上修改只对当前用户有效,即Shell脚本命令只能当前用户使用,不影响其他用户
规定: 所有的自定义脚本文件放在同一个目录下,方便管理
读取控制台输入
格式为 :read -t 时间 -p 输入时的提示内容 变量名
等待控制台输入
-t
指定读取输入内容时的等待时间,超过了这个时间,就不再等待输入,若没有-t
,则表示会一直等待-p
指定读取输入内容时的提示内容
变量
- 输入命令
$变量名
获取指定变量的值(中间无空格) - 输入命令
echo "hello world"
打印内容到终端
常用系统变量
常用系统变量有:HOME
,PWD
,SHELL
,USER
- 输入命令
set
查看所有系统变量
自定义变量
- 定义变量或者变量赋值
变量名=变量值
(中间无空格) - 撤销变量
unset 变量名
- 声明静态变量
readonly 变量名
(注意:该变量不能被unset
)
Shell
当中所有的变量默认都是字符串类型,若字符串当中有空格,那么整个字符串应该用单引号或双引号括起来
- 输入命令
export 变量名
将指定的变量设置为全局变量,这样在其他的Shell脚本文件当中就可以直接使用该变量
特殊变量
$n 外部传参
通过$n
在脚本文件内部接受外部参数,n表示数字,$0
表示脚本名称,$1~$9
表示命令行执行脚本时,脚本路径后面跟着的九个外部参数,如果参数超过了九个,要大括号包含,如$[10]
表示第10个外部参数
所有的linux命令本质上就是脚本,其格式是脚本名 外部参数1 外部参数2 ……
,如上图,ls
就是脚本名称(脚本路径),-l
就是外部参数1
$#
- 通过
$#
在脚本文件内部接受外部参数的个数,常作为脚本文件内部的循环条件
$*
和 $@
$*
这个变量代表命令行中的所有外部参数,但是当$*
加上双引号时, 它会将所有外部参数看作一个整体$@
这个变量代表命令行中的所有外部参数,不过当$#
加上双引号时 它会将各个外部参数自动分割开(可以用作for循环)
for 变量 in "$@"; #会根据外部参数个数来循环
do
程序
done
for 变量 in "$#"; #只会循环一次
do
程序
done
$?
- $? 这个变量用来判断上一条命令是否执行成功,若执行成功,返回0,否则返回非0
运算符
- 输入命令
变量名=$[运算式]
获取运算式的运算结果并存入对应变量当中
条件判断
- 输入命令
test 条件
或者[ 条件 ]
,如果条件为真,则命令执行成功,若条件为假,则命令执行失败(通常该命令要结合$?
命令一起来使用)
- 两个整数比较大小如下:
格式为 [ 整数1 -lt 整数2 ]
(-lt表示小于)
- 判断文件或目录对应当前用户而言是否具有某个权限如下:
格式为[ -w或r或x 文件路径或文件名 ]
- 判断文件或目录是否存在,若存在,则是否为文件或者目录
格式为:[ -e或f或d 文件路径或文件名 ]
- 多条件的与或判断(逻辑运算)
格式为:[ 条件 ] && echo "OK" || echo "not OK"
流程控制
if判断
单分支格式为:
if [ 条件判断 ]
then
程序
fi
多分支格式为:
if [ 条件判断 ]
then
程序
elif [ 条件判断 ]
then
程序
else
程序
fi
case语句
格式为:
case $变量名 in
"值1")
程序1
;;
"值2")
程序2
;;
*) #星号表示默认值
默认程序
;;
esac
for循环
格式1为:
for ((初始值;循环控制条件;变量变化))
do
程序
done
格式2为:
for 变量 in 值1 值2 值3……;
do
程序
done
while 循环
格式为:
while [ 条件 ]
do
程序
done
函数
系统函数
- 处理绝对路径下文件名的函数:
格式1为:
basename 文件的绝对路径
返回文件名格式2为:
basename 文件的绝对路径 文件后缀名
返回去掉后缀名的文件名
- 获取文件对应的
工作目录
(工作目录=绝对路径-文件名)
格式1为:
dirname 文件的绝对路径
返回文件对应的工作目录
自定义函数
Shell脚本是逐行执行的,因此在调用函数之前,都要先声明函数
自定义函数的返回值只能是
0~255
,其中0
表示函数正常执行,且返回值只能通过系统变量$?
来获得,若无返回值,则同样输出0~255
,此时0
表示该自定义函数中最后一条命令执行成功
定义格式为:
[ function ] 函数名()
{
程序
return 0;
}
# 函数的参数只能通过外部参数来传递
read -p "please input:" n1; #等待控制台输入
read -p "please input:" n2;
# 函数调用
函数名 n1 n2 #直接写在Shell脚本文件中
#若要使用函数的结果,则需要自己设置变量,到函数中去接收其最终的结果
Shell 工具(重点)
cut(常用)
cut
命令从文件的每一列剪切字节,字符,字段并将这些剪切下的内容进行输出。
格式为: cut -d " " -f 2 文件名
输出文件对应列的内容(空格作为分隔符,输出文件内容的第二列)
-d + 分隔符
通过分隔符来对列进行划分-f + 列号
(从1开始算),列与列之间通过分隔符来划分-c 按字符(每列的内容)进行分割
,后 +n 表示第几列,如:-c 2
(无分隔符概念)
cat 文件名 | grep 行内容 | cut -d " " -f 2-
#首先通过cat 获取整个文件的内容, 在通过 grep 筛选出对应的行,
#再在指定行当中选定从第2列开始以后的所有内容
指令1 | 指令2
当中|
表示管道符,其能够将前面指令运行的结果传递给后面的指令(作为后面指令的输入)
awk
格式为 awk -F ":" '/^root/{print $n}' 文件名
-F 后面是 分隔符,
'/查找的行内容/{查找后要执行的操作}'
上述指令作用:将冒号作为分割符,查找以root
开头的内容,查找完成后,打印第n列
的内容
awk -F ":" 'BEGIN{print "内容"}/^root/{print $n1 "," $n2}END{print "内容"}' 文件名
# 根据查询到的指定内容,打印第n1列和第n2列,并以逗号隔开
# 同时在打印结果的开头和结尾各自添加内容
awk -v 变量名=变量值 -F ":" '/^root/{print $n+变量名}' 文件名
#最终打印结果=第n列的每个值均加了变量值并输出
注意: 在print
内部,双引号""
表示用户自定义的字符串,无双引号就表示是变量
awk 内置变量
这些内置变量可以直接在
- FILENAME 文件名
- NR 当前所在行的行号
- NF 分隔过后,列的个数
awk在查找完指定内容后,进行打印时,会逐行依次打印
Shell的正则表达式
^xxx
匹配到所有以xxx开头的内容,如:grep ^a
匹配到所有以a开头的内容xxx$
匹配到所有以xxx结尾的内容,如:grep a$
匹配到所有以a结尾的内容.
匹配任意一个字符字符*
匹配到该字符连续出现0次或者多次[6,8]
匹配到6或者8[a-w]
匹配到a~w中的任意一个\字符
转义字符,如\$
匹配到 $