一文快速上手shell编程
博文目录(并未实现,下次更新时想想办法)
shell概述
shell脚本入门
第一个Shell脚本:HelloWorld
多命令处理
shell变量
自定义变量&系统变量
特殊变量
运算符
流程控制
if
case
for
while
read关键字
函数
系统函数
自定义函数
shell工具
cut
sed
awk
sort
Shell概述
Shell是一种具备特殊功能的脚本语言,它提供了用户与Linux内核进行交互操作的一种接口,接收用户输入的命令,并把它送入Linux内核去执行。Shell与Linux的关系可简单用下图进行表示。
Linux系统往往有其自带的Shell脚本解释器,在Linux终端使用echo $SHELL
即可查看到出系统当前正使用的shell解释器,centos中代码执行效果如下:
(base) [root@VM-8-10-centos bin]# echo $SHELL
/bin/bash
Shell脚本入门
第一个Shell脚本:HelloWorld
目的:打印出“HelloWorld”
#!/bin/bash
echo "Hello World by Shell"
- 脚本格式:以解析器开头,即
#!/bin/bash
- 使用
touch
新建helloworld.sh文件,编辑好在命令行中使用sh/bash
调用解释器执行即可,也可通过chomd更改文件权限以摆脱对解释器执行的依赖。
多命令处理
目的:使用shell在指定目录下建立txt文件,并向其中写入一行字符
#!/bin/bash
cd /root/practice/shell/txt/
touch love.txt
echo "SZ loves DHS" >>love.txt
-没有任何技巧,shell多命令处理的本质就是逐条执行Linux命令
shell变量
自定义变量&系统变量
常用的几个系统变量(根/当前目录、Shell解释器、当前用户名)如下:
(base) [root@VM-8-10-centos ~]# echo $HOME
/root
(base) [root@VM-8-10-centos ~]# echo $PWD
/root
(base) [root@VM-8-10-centos ~]# echo $SHELL
/bin/bash
(base) [root@VM-8-10-centos ~]# echo $USER
root
自定义变量的语法较为简单,使用“变量名=值”即可完成变量自定义
(base) [root@VM-8-10-centos ~]# AAA=100
(base) [root@VM-8-10-centos ~]# echo $AAA
100
- 值得注意的是,赋值“=”的左右两边不能有空格,这和很多程序员的书写习惯产生了冲突。
- 使用
unset AAA
即可删除该变量
可使用关键字readonly建立静态变量,静态变量无法使用unset进行删除
(base) [root@VM-8-10-centos ~]# readonly BBB=1
(base) [root@VM-8-10-centos ~]# echo $BBB
1
(base) [root@VM-8-10-centos ~]# unset BBB
-bash: unset: BBB: cannot unset: readonly variable
-
变量名称由字母数字下划线构成,但是不能以数字开头
-
在bash中,所有变量默认类型均为字符串类型,无法直接进行数值计算
(base) [root@VM-8-10-centos ~]# CCC=1+2 (base) [root@VM-8-10-centos ~]# echo $CCC 1+2
-变量值如有空格,可以将空格引用起来或者将整个值引用起来(单双引号均可)
(base) [root@VM-8-10-centos ~]# DDD=Susie' 'loves' 'Eden (base) [root@VM-8-10-centos ~]# echo $DDD Susie loves Eden (base) [root@VM-8-10-centos ~]# DDD='Susie loves Eden' (base) [root@VM-8-10-centos ~]# echo $DDD Susie loves Eden
使用export关键字可以建立全局变量,可供其他shell脚本使用,效果如下
(base) [root@VM-8-10-centos txt]# cd /root/practice/shell
(base) [root@VM-8-10-centos shell]# vim HelloWorld.sh
(base) [root@VM-8-10-centos shell]# export DDD
(base) [root@VM-8-10-centos shell]# bash HelloWorld.sh
Hello World by Shell
Susie loves Eden
特殊变量
$n:shell脚本中参数变量,其中$0代表该脚本名称,$1-$9代表第1-9个参数,10以上的参数需要用大括号包含,如%{10}
上述解释略显苍白,可编写parameter.sh如下:
#!/bin/bash
echo "$0 $1 $2 $3 $4 $5 $6 $7"
执行脚本时,分别使用带有不同参数的命令,执行情况如下:
(base) [root@VM-8-10-centos shell]# bash parameter.sh
parameter.sh
(base) [root@VM-8-10-centos shell]# bash parameter.sh a b se wwe sdfa sf
parameter.sh a b se wwe sdfa sf
(base) [root@VM-8-10-centos shell]# bash parameter.sh a d s w e Susie Eden xxx
parameter.sh a d s w e Susie Eden
超过$8之后的参数,将不会被记录打印出
&#:记录最后一个参数的编号
编写parameter.sh如下:
#!/bin/bash
echo "$0 $1 $2 $3 $4 $5 $6 $7"
echo $#
命令执行情况如下:
(base) [root@VM-8-10-centos shell]# bash parameter.sh a d s w e Susie Eden xxx
parameter.sh a d s w e Susie Eden
8
(base) [root@VM-8-10-centos shell]# bash parameter.sh
parameter.sh
0
$*:获取全部的脚本参数(合n为1)
$@:获取全部的脚本参数(仍然各自独立)
使用cat命令将变量打印追加进parameter.sh中:
(base) [root@VM-8-10-centos shell]# cat >>parameter.sh
echo $*
echo $@
^C
命令执行情况如下:
(base) [root@VM-8-10-centos shell]# bash parameter.sh a b c d e f g h i j k l m n
parameter.sh a b c d e f g
14
a b c d e f g h i j k l m n
a b c d e f g h i j k l m n
$?:返回上一条命令执行情况,执行成功则返回0,执行失败则返回相应的错误数字
具体表现如下:
(base) [root@VM-8-10-centos shell]# bash parameter.sh a b c d e f g h i j k l m n
parameter.sh a b c d e f g
14
a b c d e f g h i j k l m n
a b c d e f g h i j k l m n
(base) [root@VM-8-10-centos shell]#
运算符
shell提供了以下两种关键字的格式来实现数值计算:
- $[运算式]或$((运算式))
- expr +,-,*,/,%实现加减乘除取余运算,··代表括号,使用此种格式运算时,运算符与变量之间必须存在空格
值得注意的是,在算式中使用变量时,字符串变量自动变为0参与计算
条件判断
基本语法:[ condition ],两边必须存在空格!
常用的判断条件主要有以下三类:
- 变量对比:“=”字符串比较、-lt、-le、-eq、-gt、-ge、-ne比大小
- 文件权限判断:-r可读、-w可写、-x可执行
- 文件类型判断:-f文件存在并且是一个file类型的、-e文件存在、-d文件存在并且是一个目录
在实际执行判断语句后,需要通过输出$?的值获取判断结果
在进行多条件判断时,使用&&和||实现“与”“或”操作,值得注意的是,&&的前一条命令执行成功后才会执行后一条命令,||的前一条命令执行失败后,才会执行下一条命令,命令执行情况如下:
(base) [root@VM-8-10-centos shell]# [ 25 -ge 21 ] && echo ok || echo notok
ok
(base) [root@VM-8-10-centos shell]# [ 25 -lt 21 ] && [ ] || echo none
none
流程控制
if
基本语法:
if[ 条件表达式 ];then
程序
fi
或者
if[ 条件表达式 ]
then
程序
fi
值得注意的是,if和[]中间都要加入空格!
case
基本语法:
case $变量名 in
"case1")
程序1
;;
...
"casen")
程序n
;;
*)
兜底程序(都没符合就执行它)
;;
esac
非常常规,语法依旧反人类
for
基本语法:
for((初始值;循环条件;变量变化))
do
程序
done
值得注意的是,循环变量不需要在开头定义,程序运算需要符合运算式书写规则,1-100累加的for.sh如下所示:
#!/bin/bash
s=0
for((i=0;i<=100;i++))
do
s=$[$s+$i]
done
echo $s
(base) [root@VM-8-10-centos shell]# bash for.sh
5050
此外,还可以使用以下格式调用循环:
for 循环变量 in 变量组合
do
程序
done
语法较简单,和python极为类似
while
基本语法:
while[ 条件判断式 ]
do
程序
done
非常常规,不做过多解释
read关键字
read的基本用法是读取控制台的输入内容
基本语法:read(选项)(变量)
其中选项分为-p(指定读取值时的提示符)和-t(指定读取值时等待的时间(秒))
仍然是较为苍白的解释,这里直接上代码,编写一个10s内要求用户输入名字的sh脚本welcome.sh如下:
read -t 10 -p "请你在10s内输入你的名字:" name
echo "欢迎$name"
执行情况如下:
(base) [root@VM-8-10-centos shell]# bash welcome.sh
请你在10s内输入你的名字:丁晗姝小可爱
欢迎丁晗姝小可爱
函数
系统函数
dirname:获取文件绝对路径,但前提是得给出完整绝对路径加文件名,相当于只起到了删除文件名的作用,其基本语法为dirname xxxxx(绝对路径+文件名)
basename:删除前缀(一直到最后一个'/'为止的字符串),然后再删除指定后缀(也可以不指定不删除),其基本语法为basename xxx(前缀)/xxxxx 后缀
直接上代码展示:
(base) [root@VM-8-10-centos shell]# dirname /root/practice/shell/welcome.sh
/root/practice/shell
(base) [root@VM-8-10-centos shell]# basename /root/practice/shell/welcome.sh
welcome.sh
(base) [root@VM-8-10-centos shell]# basename /root/practice/shell/welcome.sh .sh
welcome
自定义函数
基本语法:
function funname[()]
{
Action;
[return int;]
}
funname
值得注意的是,函数返回值可以通过变量$?获得,可以加return返回,如果不加,将以最后一条命令运行结果作为返回值,return后的返回值范围在(0-255)之间
直接上一个两数相加的代码sum.sh:
#!/bin/bash
function sum()
{
s=0
s=$[$1+$2]
echo "两数之和为:$s"
}
read -p "请输入第一个数:" a1
read -p "请输入第二个数:" a2
sum $a1 $a2
执行情况如下:
(base) [root@VM-8-10-centos shell]# bash sum.sh
请输入第一个数:123
请输入第二个数:321
两数之和为:444
shell工具
cut
cut是用以处理文本数据的shell工具,使用范围很广,使用方式也多种多样,常常配合linux管道符"|"、grep等关键字使用
基本语法:cut -d 分隔符 -f 列数 文件名(一般为txt)
在一个较为复杂的例子中使用cut工具,如使用cut工具在ifconfig的查询内容中,获取到主机的ip地址,其中ifconfig的查询内容如下:
(base) [root@VM-8-10-centos shell]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.8.10 netmask 255.255.252.0 broadcast 10.0.11.255
inet6 fe80::5054:ff:fea8:6fbf prefixlen 64 scopeid 0x20<link>
ether 52:54:00:a8:6f:bf txqueuelen 1000 (Ethernet)
RX packets 14645235 bytes 2362579326 (2.2 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 14697289 bytes 2675144571 (2.4 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 678 bytes 80489 (78.6 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 678 bytes 80489 (78.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
我们需要通过管道符"|"进行一步一步的切割,分析得出以下切割步骤:
- 使用ifconfig eth0查询物理网卡信息
- 使用grep获取"inet# 10.0.8.10...."所在的一行
- 以" "作为切割符,使用cut切割,保留第10列(数空格)
切割代码如下:
(base) [root@VM-8-10-centos shell]# ifconfig eth0 | grep "inet " | cut -d " " -f 10
10.0.8.10
sed
sed是shell的流编辑器,一次处理一行的内容,把当前处理的行储存在临时缓存区中,这样不断重复直到文件末尾(不会改变文件内容)
基本语法:sed[选项参数] 命令 文件
- 其中选项参数为"-e",添加后,可以执行多条命令
- 常用的命令为a(新增)、d(删除)、s(查找并替换)等等
使用文本数据shu.txt进行练习
shu han
zhan shu
xi xi
huan huan
han shu
shu zhan
- 将"hao hao"插入到文本数据中的第二行,代码如下:
(base) [root@VM-8-10-centos shell]# sed "2a hao hao" shu.txt shu han zhan shu hao hao xi xi huan huan han shu shu zhan
- 将shu.txt中带有huan的行删除,代码如下:
(base) [root@VM-8-10-centos shell]# sed "/huan/d" shu.txt shu han zhan shu xi xi han shu shu zhan
- 将shu.txt中的xi替换成love,代码如下(加g为全局替换,不加则只替换第一个):
(base) [root@VM-8-10-centos shell]# sed "s/xi/love/g" shu.txt shu han zhan shu love love huan huan han shu shu zhan
- 将shu.txt第二行删除,并将xi替换乘love,代码如下(用到选项参数-e):
(base) [root@VM-8-10-centos shell]# sed "s/xi/love/g" shu.txt shu han zhan shu love love huan huan han shu shu zhan
以上修改均在缓冲空间中完成,均不改变原文件内容
awk
awk是shell的文本分析工具,它可以把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理
基本语法:awk[选项参数]‘文本1{程序1} 文本2{程序2}...’ 文件名,其选项参数包括-F(指定输入文件拆分的分隔符)、-v(赋值一个用户定义变量)等等
其执行逻辑为查找设定的文本,并执行相应的程序操作,待查找文本的格式为正则匹配的格式
除此之外,awk还包含以下三个内置变量,帮助用户进行更丰富的操作组合:
- FILENAME:操作的文件名
- NR:已读的记录数(以行为单位记录)
- NF:浏览记录切割后列的个数
备注:此项功能太过强大,无法快速上手,故只进行简单介绍
sort
sort命令在shell里非常有用,它可以将文件进行排序,并将排序结果标准输出
基本语法:sort(选项)(参数)
其选项包含以下几种常用类型:-n依照数值大小排序、-r以相反顺序排序、-t设置排序时所用的分隔符、-k指定需要排序的列
准备一组数据进行实战演练,待排序数据sort.sh如下:
bb:40:5.4
bd:20:4.2
xz:50:2.3
cls:10:3.5
ss:30:1.6
以:分割后的第三列倒序排序的代码如下:
(base) [root@VM-8-10-centos ~]# sort -t : -nrk 3 sort.sh
bb:40:5.4
bd:20:4.2
cls:10:3.5
xz:50:2.3
ss:30:1.6
多学多练多记才能熟练运用,本周开坑全栈开发,可能先从算法更起吧,要加油哦!
感谢大神~受益匪浅:)
不错不错,受益匪浅