Shell脚本(4)
Shell脚本(四)正则表达式+文本处理
一、正则表达式
1.正则表达式概述
定义:又称正规表达式,在代码常简写为regex,regexp或PE,使用单个字符串来描述、匹配一系列符合某个语法规则的字符串,由普通字符和元字符组成
用途:对于系统管理员来说,正则表达式是必备技能
2.基础正则表达式:grep,sed
实例grep
- 查找特定字符
-n表示显示行号、-i表示不区分大小写
grep -n 'the' test.txt 查找含有the的行,并显示行号
grep -in 'the' test.txt 查找含有the的行,忽略大小写并显示行号
grep -vn 'the' test.txt 查找不包含the的行,显示行号
- 利用中括号"[]"l来查找集合字符
grep -n 'sh[io]rt' test.txt 查找包含shirt的行和包含short的行
grep -n 'oo' test.txt 查找包含重复单个字符"oo"的行
grep -n '[^w]oo' test.txt 查找"oo"前面不是"w"的字符串所在的行
grep -n '[^a-z]oo' test.txt 查找"oo"前面不是小写字母的字符串所在的行
grep -n '[^A-Z]oo' test.txt 查找"oo"前面不是大写字母的字符串所在的行
grep -n '[0-9]' test.txt 查找包含数字的行
- 查找行首"^"与行尾字符"$"
grep -n '^the' test.txt 查找以"the"字符串为行首的行
grep -n '^[a-z]' test.txt 查找以小写字母为开头的行
grep -n '^[A-Z]' test.txt 查找以大写字母为开头的行
grep -n '^[^a-zA-Z]' test.txt 查找不以字母为开头的行
grep -n '\.$' test.txt 查找以小数点(.)为结尾的行
grep -n '^$' test.txt 查找空白行
- 查找任意一个字符"."与重复字符"*"
grep -n 'w..d' test.txt 查找共有4个字符的字符串,并以w开头,d结尾所在的行
grep -n 'o*' test.txt 查找拥有≥0或≥1个"o"的重复字符的行,打印文本所有内容
grep -n 'oo*' test.txt 查找包含≥1个"o"的重复字符的行,包含o,oo,ooo,oooo…
grep -n 'ooo*' test.txt 查找包含≥2个"o"的重复字符的行,包含oo,ooo,oooo…
grep -n 'woo*d' test.txt 查找以w开头d结尾,中间包含至少一个o的字符串所在的行
grep -n 'w.*d' test.txt 查找以w开头d结尾,中间字符可有可无的字符串的行
grep -n '[0-9][0-9]*' test.txt 查找任意数字所在的行
- 查找连续字符范围"{}"
grep -n 'o\{2\}' test.txt 查找2个o的字符的字符串所在的行
grep -n 'wo\{2,5\}d' test.txt 查找以w开头以d结尾,中间包含2-5个o的字符串所在的行
grep -n 'wo\{2,\}d' test.txt 查找以w开头以d结尾,中间包含2个o以上字符串所在的行
元字符总结
3.扩展正则表达式
二、文本处理器
1.sed工具
用法
sed[选项] '操作' 参数
sed [选项] -f scriptfile 参数
选项
-e或--expression=:表示用指定命令或者脚本来处理输入的文本文件
-f或--file=:表示用指定的脚本文件来处理输入的文本文件
-h或--help:显示帮助。
-n、--quiet或silent:表示仅显示处理后的结果
操作
-i: 直接编辑文本文件。
a:增加,在当前行下面增加一行指定内容。
c:替换,将选定行替换为指定内容。
d:删除,删除选定的行。
i:插入,在选定行上面插入一行指定内容。
p: 打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以ASC||码输出。其通常与"-n"选项一起使用。
s:替换,替换指定字符。
y:字符转换。
2.用法示例
1)输出符合条件的文本(p表示正常输出)
sed -n 'p' test.txt 输出所有内容,等同于cat test.txt
sed -n '3p' test.txt 输出第3行
sed -n '3,5p' test.txt 输出3~5行
sed -n 'p;n' test.txt 输出所有奇数行,n表示读入下一行资料
sed -n 'n;p' text.txt 输出所有偶数行,n表示读入下一行资料
sed -n '1,5{p;n}' test.txt 输出第1~5行之间的奇数行(第1、3、5行)
sed -n '10,${n;p}' test.txt 输出第10行至文件尾之间的偶数行
正则表达式以"/"包围
sed -n '/the/p' test.txt 输出包含the的行
sed -n '4,/the/p' test.txt 输出从第4行至第一个包含the的行
sed -n '/the/=' test.txt 输出包含the的行所在的行号,等号(=)用来输出行号
sed -n /^PI/p test.txt 输出以PI开头的行
sed -n '/[0-9]$/p' test.txt 输出以数字结尾的行
sed -n '/\<wood\>/p' test.txt 输出包含单词wood的行,\<、\>代表单词边界
2)删除符合条件的文本(d)
n1 test.txt | sed '3d' 删除第3行
n1 test.txt | sed '3,5d' 删除第3~5行
n1 test.txt | sed '/cross/d' 删除包含cross的行
n1 test.txt | sed '/cross/! d' 删除不包含cross的行
sed '/^[a-z]/d' test.txt 删除以小写字母开头的行
sed '/\.$/d' test.txt 删除以点结尾的行
sed '/^$/d' test.txt 删除所有空行
3)替换符合条件的文本
s(字符串替换)、C (整行/整块替换)、y (字符转换)
sed 's/the/THE/' test.txt 将每行中的第一个the替换为THE
sed 's/l/L/2' test.txt 将每行中的第3个l替换为L
sed 's/the/THE/g' test.txt 将文件中的所有the替换为THE
sed 's/o//g' test.txt 将文件中的所有o删除(替换为空串)
sed 's/^/#/' test.txt 在每行行首插入#号
sed '/the/s/^/#/' test.txt 在包含the的每行行首插入#号
sed 's/$/EOF/' test.txt 在每行行尾插入字符串EOF
sed '3, 5s/the/THE/g' test.txt 将第3~5行中的所有the替换为THE
sed'/the/s/o/0/g' test.txt 将包含the的所有行中的o都替换为0
4)迁移符合条件的文本
H.复制到剪切板:,g、G将剪贴板中的数据覆盖/追加至指定行,
w保存为文件;r读取指定文件: a,追加指定内容
sed '/the/ {H;d} ;$G' test.txt 将包含the的行迁移至文件末尾,{;}用于多个操作
sed '1,5{H;d} ;17G' test.txt 将第1~5行内容转移至第17行后
sed '/the/w out.file' test.txt 将包含the的行另存为文件out.file
sed '/the/r /etc/hostname' test.txt 将文件/etc/hostname的内容添加到包含the的每行以后
sed '3aNew' test.txt 在第3行后插入一个新行,内容为New
sed '/the/aNew' test.txt 在包含the的每行后插入一个新行,内容为New
sed ' 3aNew1 \nNew2' test.txt 在第3行后插入多行内容,中间的\n表示换行
5)使用脚本编辑文件
vim opt.list
1,5H
1,5d
17G
sed -f opt.list test.txt
6)sed直接操作文件示例
编写一个脚本,用来调整vsftpd服务配置:禁止匿名用户,但允许本地用户(也允许写入)
原来的配置文件选项
覆盖之后的
2.awk工具
用法
awk 选项 '模式或条件 {编辑指令}' 文件1 文件2 …过滤并输出文件符条件的内容
awk -f 脚本文件 文件1 文件2 … 从脚本中调用编辑指令,过滤并输出内容
逻辑操作符
&&:与 ||:或 !:非 +:加 -:减 *:乘 /:除 %:取余 ^:乘方
查找出/etc/passwd的用户名,用户ID、组ID等列
awk -F ':' '{print $1,$3,$4}' /etc/passwd
awk工作原理
特殊的内建变量
FS:指定每行文本的字段分隔符,默认为空格或制表位
NF:当前处理的行的字段个数
NR: 当前处理的行的行号(序数)
$0: 当前处理的行的整行内容
$n: 当前处理的行的第n个字段
FILENAME:被处理的文件名
RS:数据记录分隔,默认为\n,即每行为一条记录
用法
按行输出文本
awk ' {print} ' test.txt 输出所有内容,等同于cat test.txt
awk ' {print $0}' test.txt 输出所有内容,等同于cat test.txt
awk 'NR==1,NR==3{print} 'test.txt 输出第 1~3行内容
awk '(NR>=1)&& (NR<=3) {print}' test.txt 输出第1~3行内容
awk 'NR==1||NR==3{print}' test.txt 输出第 1行、第3行内容
awk '(NR%2)==1{print}' test.txt 输出所有奇数行的内容
awk '(NR%2)==0{print}' test.txt 输出所有偶数行的内容
awk '/^root/ {print}' /etc/passwd 输出以root开头的行
awk '/nologin$/ {print}' /etc/passwd 输出以nologin结尾的行
awk 'BEGIN {x=0} ; /\/bin\/bash$/{x++};END {print x}' /etc/passwd 统计以/bin/bash结尾的行数,等同于grep -c "/bin/bash$" /etc/passwd
awk 'BEGIN{RS=" "} ;END{print NR}' /etc/squid/ squid.conf 统计以空行分隔的文本段落数
按字段输出文本
awk '{print $3}' test.txt 输出每行中(以空格或制表位分隔)的第3
awk '{print $1,$3}' test.txt 输出每行中的第1、3个字段
awk -F ":"'$2==""{print}' /etc/shadow 输出密码为空的用户的 shadow记录
awk 'BEGIN {FS=":"}; $2==""{print}' /etc/shadow 输出密码为空的用户的shadow记录
awk -F ":" '$7~" /bash" {print $1}' /etc/passwd 输出以冒号分隔且第 7个字段中包含/bash 的行的第1个字段
awk '($1~"nfs")&&(NF==8) {print $1,$2}' /etc/services 输出包含8个字段且第1个字段中包含nfs的行的第1、2个字段
awk -F ":" '($7!="/bin/bash")&& ($7!="/sbin/nologin") (print}' /etc/passwd 输出第7个字段既不为/bin/bash也不为/sbin/ nologin的所有行
通过管道、双引号调用shell命令
awk -F: '/bash$/(print | "wc -l")' /etc/passwd 调用wc -1命令统计使用bash的用户个数,等同于grep -c "bash$" /etc/passwd
awk 'BEGIN (while ("w" I getline) n++ ; (print n-2))' 调用W命令,并用来统计在线用户数
awk 'BEGIN ( "hostname" | getline ; print $0]' 调用hostname,并输出当前的主机名
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~