提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
前言
今天学习的是Shell脚本的编写,Shell脚本是一种编写在Unix或类Unix操作系统上的脚本程序,用于执行一系列的命令。它由一系列的命令和控制结构组成,可以通过直接在命令行中输入脚本名称来执行,也可以通过给脚本文件添加执行权限后直接运行该文件。
Shell脚本通常用于自动化任务,可以编写一些简单或复杂的脚本来执行重复性的工作,提高工作效率。它可以像编程语言一样实现流程控制、变量定义、函数调用等功能。Shell脚本可以用多种脚本语言编写,如Bash、Csh、Ksh等,其中Bash是最常用的脚本语言。
使用Shell脚本可以实现很多任务,比如文件处理、系统管理、数据处理等。它可以调用系统命令、执行外部程序、处理输入输出、控制进程等。Shell脚本的优点是简单易学、灵活性强,但在处理大规模任务和复杂逻辑时可能效率较低,适用于快速编写和执行一些小规模任务。
提示:以下是本篇文章正文内容,下面案例可供参考
一、概述
1. 概念
脚本就是将手动一次性执行的命令进行规范且自动化
2. 学习路径
2.1表达式
变量 | 预定义变量 |
位置变量 | |
自定义变量 | |
运算符 | 数学运算 |
数值比较 | |
字符串比较 | |
文件判断 | |
布尔运算符 |
2.2 语句
条件语句 | if |
分支语句 | case |
循环语句 | for |
while |
2.3 函数
函数:函数是以函数名()跟{}括起来的内容组成。函数可以实现一些功能封装,同时函数也支持与脚本类似的参数解析逻辑。
2.4 正则表达式
标准正则
扩展正则
2.5 文件操作四剑客
find
egrep
sed
awk
二、表达式
1.shell
shell命令解释环境
类型
sh
ash
bsh
csh
bash
tcsh
dsh
zsh
查看系统中支持的shell
cat /etc/shells
查看系统默认shell
echo $SHELL
2.表达式
2.1 变量
2.2.1组成
变量名 | 不会变化 | 杯子 | |
瓢 | |||
容器... | |||
声明规范 | 不能是数字或数字开头 | ||
以_或字母开头 | |||
变量名中不能包含特殊字符 | |||
声明方法 | 驼峰式 | userName | |
双驼峰 | UserName | ||
shell写法 | user_name | ||
username | |||
USERNAME | |||
变量值 | 不断变化 | 承载的物体 | |
数字、字符 |
2.2.2 类型
系统内置变量(环境变量) | env |
自定义变量 | varName=varValue | |||
等号两边不能有格 | ||||
数字 | var1=1 | |||
字符串 | shell中可以不使用引号 | |||
当包含有空格时,需要使用引号 | ||||
引号的用法 | 不会引用变量值 | 单引号 | ' | |
会应用变量值 | 双引号 | " | ||
引用命令结果 | 反撇号 | ` | ||
$(命令) | 应用场景较多 |
位置变量 | 脚本后参数所在的位置 |
$1 | |
... | |
$9 |
预定义变量 | $0 | 脚本本身的名称 | |
$# | 脚本后参数的个数 | ||
$* | 脚本运行时参数的内容(整体输出) | ||
$@ | 脚本运行时参数的内容(逐个输出) | ||
$? | 脚本运行完毕后的返回值 | ||
默认情况 | 0 成功 | ||
非0 失败 |
2.2.3 作用域
默认变量只在当前shell下生效
若要在当前及其子shell下生效,需要声明为全局变量
export
2.2.4 输出
echo $varName
2.2.5 shell中的字符串
string
赋值: str1=foodfornoting.gpg
(1)获得字符串的长度
语法: ${#StringName}
案例: echo ${#str1}
输出结果:17
(2)字符串取子串
语法: ${#StringName:position:lenght}
案例: echo ${str1:0:3}
输出结果:foo
注意:lenght没有定义时,一直取到字符串的结尾!
(3)字符串的截取
a)从左至右截取最后一个匹配字符串string之后的所有字符串
语法: ${StringName##*string}
案例: echo ${str1##*fo}
输出结果:rnoting.gpg
b)从左至右截取第一个匹配字符串string之后的所有字符串
语法: ${StringName#*string}
案例: echo ${str1#*fo}
输出结果:odfornoting.gpg
c)从右至左截取最后一个匹配字符串string之后的所有字符串
语法: ${StringName%%string*}
案例: echo ${str2%%o*}
输出结果:f
d)从右至左截取第一个匹配字符串string之后的所有字符串
语法: ${StringName%string*}
案例: echo ${str2%o*}
输出结果:foodforn
(4)字符串的拼接
语法: StringName3=${StingName1}${StringName2}
案例: str1=Hello
str2=,Jack!
str3=${str1}${str2}
echo ${str3}
输出结果: Hello,Jack!
(5)字符串替换:
语法: ${StringName/OldString/NewString}
案例: str1=foodfornoting.gpg
echo ${str1/oo/kk}
输出结果:fkkdfornoting.gpg
2.2 运算符
数学运算
数学运算 | + - * / % | * 作为乘号时需要加转义符\ | |
运算方法 | expr | expr $a + $b | |
$((a+b)) | echo $((a+b)) | ||
$[a+b] | echo $[a+b] | ||
注意 | shell不支持浮点数的显示 |
比较运算
条件测试 | test var1 比较符 var2 | ||
[ var1 比较符 var2 ] | |||
&& | [ $a -ne $b ] && echo OK | 条件 && 输出结果 | |
条件为真输出 | |||
|| | [ $a -ne $b ] || echo OK | 条件 || 输出结果 | |
条件为假输出 |
数值比较
-eq | 等于 |
-ne | 不等于 |
-lt | 小于 |
-le | 小于等于 |
-gt | 大于 |
-ge | 大于等于 |
字符串比较
= | 字符串一致 |
!= | 字符串不一致 |
-z | 字符串为空 |
! -z | 字符串不为空 |
文件比较
-e | 文件或目录是否存在 |
-f | 是否为文件 |
-d | 是否为目录 |
-r | 判断文件是否可读 |
-w | 判断文件是否可写 |
-x | 判断文件是否可执行 |
逻辑运算符
&& | -a | 并且,有假则假,全真为真 | [ -r 111 -a -w 111 -a -x 111 ] |
[ -r 111 ] && [ -w 111 ] && [ -x 111 ] | |||
[ -x /root/file1 -a -d /root/file1 ] | |||
[ -x /root/file1 ] && [ -d /root/file1 ] | |||
|| | -o | 或者,有真则真,全假为假 | |
! | 取反 | 有真则假,有假则真 |
2.3 shell脚本编写规范
第一行
#!/bin/bash
第二行
#脚本的说明
第三行
脚本正文
2.4 shell运行规则
没有x权限 | bash 脚本所在路径/脚本文件 | |
source 脚本所在路径/脚本文件 | 脚本存在cd 时,会切换到目标目录 | |
. 脚本所在路径/脚本文件 | ||
有x权限 | ./脚本文件 | |
脚本绝对路径/脚本文件 |
shell脚本运行追踪
bash -x 脚本所在路径/脚本文件
$[$RANDOM%100]
返回100内随机数
seq 1 10
返回1到10 的连续数字
{1..10}
返回1到10 的连续数字
seq 1.1 10.1
返回1.1 2.1 3.1.... 10.1
read -p "提示语" 变量名
读取键盘输入并赋值给变量名
2.5 语句
2.5.1 条件语句
单分支if
if [ ];then
fi
双分支if
if [ ];then
else
fi
多分支if
if [ ];then
elif [ ];then
else
fi
2.5.2 循环语句
for
for 条件(i in 值)|((i=1;i<=10;i++))
do
语句
done
while
i=1
while 条件
do
语句
let i++
done
关于$*与$@的验证
2.5.3 开关语句
case
case $1 in
条件1)
语句
;;
条件2)
语句
;;
*)
帮助信息
;;
esac
nginx启动脚本
2. 文件操作四剑客
2.1 正则表达式
2.1.1 基础正则
a)查找特定字符
cat test.txt | grep -n 'was'
b)利用[]查找集合字符
cat test.txt | grep -n 'sh[io]rt'
匹配i或者o
cat test.txt | grep -n '[^w]'
排除w
cat test.txt | grep -n '[a-h]oo'
cat test.txt | grep -n '[0-9]'
c)查找行首"^"与行尾"$"
cat test.txt | grep -n '^[A-Z]'
cat test.txt | grep '\.$'
\ 为转义符
d)查找任意一个字符"."与重复字符"*"
cat test.txt | grep -n 'w..d'
cat test.txt | grep -n 'ooo*'
e)查找连续的字符范围"{}",需要使用转义符,"\{\}"
cat test.txt | grep -n 'o\{2\}'
cat test.txt | grep -n 'wo\{2,5\}d'
cat test.txt | grep -n 'wo\{2,\}d'
2.1.2 扩展正则
a)+,重复一个或一个以上的前一个字符
cat test.txt | grep -nE 'wo+d' 或者
cat test.txt | egrep -n 'wo+d'
b)?,零个或者一个前一个字符
cat test.txt | egrep -n 'bes?t'
c)|,使用或者的方式找出多个字符
cat test.txt | egrep -n 'of|is|on'
d)(),查找组字符串
cat test.txt | egrep -n 't(a|e)st'
e)()+,辨别多个重复的组
cat test.txt | egrep -n 'A(xyz)+C'
2.1.3 常见正则表达式
数字
“^[0-9]*[1-9][0-9]*$” //正整数
“^((-\d+)|(0+))$” //非正整数(负整数 + 0)
“^-[0-9]*[1-9][0-9]*$” //负整数
“^-?\d+$” //整数
“^\d+(\.\d+)?$” //非负浮点数(正浮点数 + 0)
“^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$” //正浮点数
“^((-\d+(\.\d+)?)|(0+(\.0+)?))$” //非正浮点数(负浮点数 + 0)
“^(-?\d+)(\.\d+)?$” //浮点数
字符串
“^[A-Z]+$” //由26个英文字母的大写组成的字符串
“^[a-z]+$” //由26个英文字母的小写组成的字符串
“^[A-Za-z0-9]+$” //由数字和26个英文字母组成的字符串
“^\w+$” //由数字、26个英文字母或者下划线组成的字符串
Email
“^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$” //email地址
“^([w-.]+)@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.)|(([w-]+.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(]?)$” //Email
Url
“^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$” //url
IP
“^(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5])$” //IP地址
Tel
/^((\+?[0-9]{2,4}\-[0-9]{3,4}\-)|([0-9]{3,4}\-))?([0-9]{7,8})(\-[0-9]+)?$/ //电话号码
日期校验
/^(d{2}|d{4})-((0([1-9]{1}))|(1[1|2]))-(([0-2]([1-9]{1}))|(3[0|1]))$/ // 年-月-日 yyyy-MM-dd / yy-MM-dd 格式
"^[0-9]{4}-((0([1-9]{1}))|(1[1|2]))-(([0-2]([0-9]{1}))|(3[0|1]))$" // 年-月- 日 yyyy-MM-dd 格式
/^((0([1-9]{1}))|(1[1|2]))/(([0-2]([1-9]{1}))|(3[0|1]))/(d{2}|d{4})$/ // 月/日/年
2.2 grep进阶
选项
-r
递归扫描指定目录下的每一个文件
-l
只显示匹配到指定关键字的文件名,而不是文件内容
案例
查看/etc目录下所有包含bash的文件名
grep -rl bash /etc
egrep
完美支持正则表达式
2.3 find进阶
按照权限查找
-perm
按照时间戳查找
-atime
-mtime
-ctime
-exec
find /var/spool/mail -type f -exec rm -rf {} \;
xargs
find /var/spool/mail -type f | xargs rm -rf
2.4 sed
语法
sed [选项] '操作' 参数
sed [选项] -f scriptfile 参数
选项
-e | 表示用指定命令或脚本处理 |
-f | 指定脚本文件 |
-h | 帮助 |
-n | 表示仅显示处理后的结果 |
-i | 直接编辑文本文件 |
-r | 支持扩展正则 |
操作
a | 增加,在当前行下面以行增加指定内容 |
c | 替换,将选定行替换 |
d | 删除,删除指定行 |
i | 插入,在选定行的上面插入一行 |
p | 打印 |
s | 替换,替换成指定字符 |
y | 字符转换 |
案例
1.输出符合条件的文本:
sed -n 'p' test.txt #相当于cat
sed -n '3p' test.txt #打印第3行
sed -n '3,6p' test.txt #打印第3到6行的内容
sed -n 'p;n' test.txt #打印奇数行
sed -n 'n;p' test.txt #打印偶数行
sed -n '1,6{p;n}' test.txt #打印1到6行之间的奇数行
sed -n '5,${p;n}' test.txt #从第5行开始打印奇数行
sed -n '/goo/p' test.txt #匹配goo
sed -n '5,/goo/p' test.txt #匹配从第5行开始到包含goo的行
sed -n '/goo/,10p' test.txt #匹配从包含goo的行到第10行结束
sed -n '/the/=' test.txt #打印包含the的行号
2.删除符合条件的文本
nl test.txt | sed '3d' #删除第3行
nl test.txt | sed '3,5d'
nl test.txt | sed '/the/d' #删除the所在行
3.替换符合条件的文本
nl test.txt | sed 's/the/TTTTTT/' #替换全文本
nl test.txt | sed '3s/good/TTTTTT/' #替换第4行
nl test.txt | sed 's/l/L/2' #替换匹配到的第2个l
4.迁移符合条件的文本
H:复制;g:覆盖;G:追加行;w:保存;r:读取;a:追加内容
sed '/the/{H;d};$G' test.txt #匹配the所在行并迁移至文件末尾
sed '3aTest' test.txt #在第3行下面新建行并写入Test
sed '/the/aTest' test.txt #匹配the所在行并在下一行写入Test
5.使用脚本编辑文件内容
vim opt.txt
1,5H
1,5d
16G
sed -f opt.txt test.txt #将1到5行迁移至16行后
6.以上修改想要直接修改文本源文件,只需要加入选项"-i"
2.5 awk
语法
awk 选项 '模式或条件{编辑命令}' 文件1 文件2 ...
awk -f 脚本文件 文件1 文件2 ...
选项
-F
指定每行的分隔符
默认分隔符为空格
内建变量
FS | 指定每行的分隔符 |
NF | 指定当前处理行的字段个数 |
NR | 当前处理行的行号 |
$0 | 当前处理行的整行内容 |
$n | 当前处理的第n个字段 |
FILENAME | 处理文件名 |
RS | 数据记录分割,默认是\n |
案例:
a)按行输出
awk '{print}' test.txt #等同cat
awk 'NR>=1&&NR<=3{print}' test.txt
awk 'NR==1,NR==3{print}' test.txt #打印1到3行
awk 'NR%2==0{print}' test.txt #打印偶数行
b)按段输出
默认以"空格"分段!
ifconfig ens33 |awk '/netmask/{print $2}' #筛选IP地址
cat /etc/shadow | awk -F : '$2=="!!"{print $1}' #打印不能登录系统的用户
c)调用shell命令
cat /etc/passwd | awk -F : '/bash$/{print | "wc -l"}' /etc/passwd #统计能够登录系统的用户个数
总结
Shell脚本是一种文本文件,由一系列命令和控制结构组成,用于执行一系列的任务。
Shell脚本可以通过直接在命令行中输入脚本名称来执行,也可以通过给脚本文件添加执行权限后直接运行该文件。
Shell脚本可以用多种脚本语言编写,如Bash、Csh、Ksh等,其中Bash是最常用的脚本语言。
Shell脚本可以调用系统命令、执行外部程序、处理输入输出、控制进程等。
Shell脚本可以实现文件处理、系统管理、数据处理等多种任务。
Shell脚本具有简单易学、灵活性强的特点,适用于快速编写和执行一些小规模任务。
Shell脚本的效率可能较低,适用于处理小规模任务和简单逻辑,对于大规模任务和复杂逻辑,可能效率较低。
Shell脚本是Unix系统中常用的自动化工具,广泛应用于系统管理、软件开发等领域。
总而言之,Shell脚本是一种简单、灵活的自动化工具,能够帮助我们自动化执行任务,提高工作效率。