Shell编程之正则表达式与文本处理器示例代码
更新时间:2026年06月29日 08:37:50 作者:刘晨鑫1
正则表达式是一种用于匹配字符串的强大工具,通过普通字符和元字符的组合,能够快速查找、替换或删除特定字符串,这篇文章主要介绍了Shell编程之正则表达式与文本处理器的相关资料,需要的朋友可以参考下
一、正则表达式
1. 正则表达式的定义
正则表达式(Regular Expression) 是一种用于匹配字符串中字符组合的模式。在Linux/Unix系统中,正则表达式被广泛应用于文本搜索、替换、过滤等操作。
2. 正则表达式用途
| 用途 | 说明 | 常用工具 |
|---|---|---|
| 文本搜索 | 在文件中查找匹配特定模式的文本 | grep、egrep |
| 文本替换 | 将匹配的文本替换为指定内容 | sed、vim |
| 文本过滤 | 提取符合条件的文本行 | awk、grep |
| 数据验证 | 验证输入格式(如邮箱、手机号) | 脚本编程 |
| 日志分析 | 从日志中提取关键信息 | awk、sed |
二、基础正则表达式
1. 基础正则表达式示例
示例1:匹配特定字符
#!/bin/bash # 创建测试文件 cat > test.txt << EOF hello world Hello Linux HELLO SHELL 12345 hello123 helloworld hello_world EOF # 匹配包含hello的行 echo "=== 匹配hello ===" grep "hello" test.txt # 匹配以h开头的行 echo "=== 匹配以h开头 ===" grep "^h" test.txt # 匹配以d结尾的行 echo "=== 匹配以d结尾 ===" grep "d$" test.txt
示例2:使用通配符
#!/bin/bash # 创建测试文件 cat > data.txt << EOF apple appple aple banana orange app123 APPLE EOF # 匹配app后面跟任意字符 echo "=== app. ===" grep "app." data.txt # 匹配a和e之间任意两个字符 echo "=== a..e ===" grep "a..e" data.txt
2. 元字符总结
| 元字符 | 作用 | 示例 | 说明 |
|---|---|---|---|
^ | 匹配行首 | ^root | 匹配以root开头的行 |
$ | 匹配行尾 | bash$ | 匹配以bash结尾的行 |
. | 匹配任意单个字符 | a.c | 匹配abc、aac、a-c等 |
* | 匹配前一个字符0次或多次 | ab*c | 匹配ac、abc、abbc等 |
[] | 匹配括号内的任意字符 | [abc] | 匹配a或b或c |
[^] | 匹配不在括号内的字符 | [^abc] | 匹配除abc外的字符 |
\ | 转义字符 | \. | 匹配点号本身 |
\{n\} | 匹配前一个字符n次 | a\{3\} | 匹配aaa |
\{n,\} | 匹配前一个字符至少n次 | a\{2,\} | 匹配aa、aaa等 |
\{n,m\} | 匹配前一个字符n到m次 | a\{2,4\} | 匹配aa、aaa、aaaa |
示例:元字符综合应用
#!/bin/bash
# 创建测试文件
cat > test.txt << EOF
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lisi:x:1000:1000:李四:/home/lisi:/bin/bash
zhangsan:x:1001:1001:张三:/home/zhangsan:/bin/bash
EOF
echo "=== 匹配以root开头 ==="
grep "^root" test.txt
echo "=== 匹配以bash结尾 ==="
grep "bash$" test.txt
echo "=== 匹配任意三个字符后跟:x: ==="
grep "^...:x:" test.txt
echo "=== 匹配用户ID为1-3位的数字 ==="
grep "x:[0-9]\{1,3\}:" test.txt
echo "=== 匹配家目录在/home下的用户 ==="
grep "/home/[a-z]\+" test.txt3. 扩展正则表达式
扩展正则表达式添加了更多元字符,使用时需要加 -E 选项(egrep命令)。
| 元字符 | 作用 | 示例 | 说明 |
|---|---|---|---|
+ | 匹配前一个字符1次或多次 | a+ | 匹配a、aa、aaa等 |
? | 匹配前一个字符0次或1次 | a?b | 匹配b、ab |
| | 逻辑或 | a|b | 匹配a或b |
() | 分组 | (ab)+ | 匹配ab、abab等 |
{n,m} | 匹配n到m次(无需转义) | a{2,4} | 匹配aa、aaa、aaaa |
示例:扩展正则表达式应用
#!/bin/bash
# 创建测试文件
cat > test.txt << EOF
apple
appple
aple
banana
banna
bananna
color
colour
colouur
123-4567
123-45678
123-456
EOF
echo "=== 使用+匹配app后面至少一个p ==="
grep -E "app+" test.txt
echo "=== 匹配color或colour ==="
grep -E "colou?r" test.txt
echo "=== 匹配banana或banna ==="
grep -E "bana{2,3}" test.txt
echo "=== 匹配电话号码格式(3-4位数字)==="
grep -E "[0-9]{3}-[0-9]{4}" test.txt
echo "=== 匹配包含apple或banana ==="
grep -E "apple|banana" test.txt三、文本处理器
1. sed工具
sed(Stream Editor) 是一种流编辑器,用于对文本进行过滤和转换。
sed基本语法
sed [选项] '命令' 文件名
常用选项
| 选项 | 作用 |
|---|---|
-n | 仅显示处理后的结果 |
-i | 直接修改文件内容 |
-e | 执行多个命令 |
-r | 使用扩展正则表达式 |
sed常用命令
| 命令 | 作用 |
|---|---|
p | 打印行 |
d | 删除行 |
s | 替换字符串 |
a | 在行后添加 |
i | 在行前插入 |
c | 替换整行 |
示例1:sed打印操作
#!/bin/bash # 创建测试文件 cat > sed.txt << EOF 第1行:Hello World 第2行:Hello Linux 第3行:Hello Shell 第4行:Hello Sed 第5行:Hello Awk EOF echo "=== 打印第2行 ===" sed -n '2p' sed.txt echo "=== 打印2-4行 ===" sed -n '2,4p' sed.txt echo "=== 打印包含Shell的行 ===" sed -n '/Shell/p' sed.txt echo "=== 打印奇数行 ===" sed -n '1~2p' sed.txt
示例2:sed删除操作
#!/bin/bash echo "=== 原始文件 ===" cat sed.txt echo "=== 删除第3行 ===" sed '3d' sed.txt echo "=== 删除2-4行 ===" sed '2,4d' sed.txt echo "=== 删除包含Linux的行 ===" sed '/Linux/d' sed.txt echo "=== 删除空行 ===" sed '/^$/d' sed.txt echo "=== 删除最后一行 ===" sed '$d' sed.txt
示例3:sed替换操作
#!/bin/bash
echo "=== 替换第一个Hello为Hi ==="
sed 's/Hello/Hi/' sed.txt
echo "=== 替换所有Hello为Hi(全局替换)==="
sed 's/Hello/Hi/g' sed.txt
echo "=== 替换第2行的Hello为Hi ==="
sed '2s/Hello/Hi/' sed.txt
echo "=== 替换2-4行的Hello为Hi ==="
sed '2,4s/Hello/Hi/g' sed.txt
echo "=== 使用&引用匹配内容 ==="
sed 's/Hello/(&)/g' sed.txt # 将Hello替换为(Hello)
echo "=== 使用正则表达式 ==="
echo "123-4567-890" | sed 's/[0-9]\{3,\}/(&)/g'示例4:sed插入和追加
#!/bin/bash echo "=== 在第2行前插入 ===" sed '2i\这是插入的行' sed.txt echo "=== 在第3行后追加 ===" sed '3a\这是追加的行' sed.txt echo "=== 在匹配行前插入 ===" sed '/Linux/i\----Linux行之前----' sed.txt echo "=== 在匹配行后追加 ===" sed '/Shell/a\----Shell行之后----' sed.txt
示例5:sed多命令组合
#!/bin/bash echo "=== 使用-e执行多个命令 ===" sed -n -e '2p' -e '4p' sed.txt echo "=== 使用分号执行多个命令 ===" sed '2d;4s/Hello/Hi/' sed.txt echo "=== 先替换再打印 ===" sed -n 's/Hello/Hi/gp' sed.txt echo "=== 实际操作文件(使用-i) ===" cp sed.txt sed.txt.bak sed -i 's/Hello/Hi/g' sed.txt echo "文件已修改:" cat sed.txt cp sed.txt.bak sed.txt # 恢复原文件
2. awk工具
awk 是一种强大的文本处理语言,主要用于数据提取和报表生成。
awk基本语法
awk [选项] '模式 {动作}' 文件名常用选项
| 选项 | 作用 |
|---|---|
-F | 指定字段分隔符 |
-v | 定义变量 |
-f | 从文件读取awk脚本 |
awk内置变量
| 变量 | 作用 |
|---|---|
$0 | 整行内容 |
$n | 第n个字段 |
NF | 字段数量 |
NR | 当前行号 |
FS | 字段分隔符 |
OFS | 输出字段分隔符 |
RS | 记录分隔符 |
ORS | 输出记录分隔符 |
示例1:awk基础操作
#!/bin/bash
# 创建测试文件
cat > awk.txt << EOF
张三 80 85 90
李四 75 88 92
王五 90 92 95
赵六 65 70 75
EOF
echo "=== 打印整行 ==="
awk '{print $0}' awk.txt
echo "=== 打印第1列(姓名)==="
awk '{print $1}' awk.txt
echo "=== 打印第2列和第3列 ==="
awk '{print $2, $3}' awk.txt
echo "=== 打印行号和内容 ==="
awk '{print NR, $0}' awk.txt
echo "=== 打印字段数量 ==="
awk '{print $0, "字段数:" NF}' awk.txt示例2:使用分隔符
#!/bin/bash
# 创建CSV格式文件
cat > data.csv << EOF
ID,姓名,部门,工资
001,张三,技术部,8000
002,李四,市场部,7500
003,王五,技术部,9000
004,赵六,财务部,7000
EOF
echo "=== 指定逗号分隔符 ==="
awk -F ',' '{print $2, $4}' data.csv
echo "=== 使用多个分隔符 ==="
echo "root:x:0:0:root:/root:/bin/bash" | awk -F '[:/]' '{print $1, $6, $8}'
echo "=== 设置输出分隔符 ==="
awk -F ',' 'BEGIN{OFS=" | "} {print $1, $2, $4}' data.csv示例3:awk模式匹配
#!/bin/bash
echo "=== 匹配包含'技术部'的行 ==="
awk -F ',' '/技术部/ {print $2, $4}' data.csv
echo "=== 匹配工资大于8000的行 ==="
awk -F ',' '$4 > 8000 {print $2, $4}' data.csv
echo "=== 匹配行号大于2的行 ==="
awk -F ',' 'NR > 2 {print NR, $0}' data.csv
echo "=== 匹配部门为技术部且工资>8500 ==="
awk -F ',' '$3 ~ /技术部/ && $4 > 8500 {print $2, $4}' data.csv示例4:awk计算和统计
#!/bin/bash
echo "=== 计算每个学生的平均分 ==="
awk '{sum=$2+$3+$4; avg=sum/3; print $1, "总分:" sum, "平均分:" avg}' awk.txt
echo "=== 统计各科平均分 ==="
awk '{
chinese+=$2
math+=$3
english+=$4
count++
} END {
print "语文平均分:" chinese/count
print "数学平均分:" math/count
print "英语平均分:" english/count
}' awk.txt
echo "=== 统计各部门工资总和 ==="
awk -F ',' 'NR>1 {
dept[$3] += $4
count[$3]++
} END {
for (d in dept) {
print d " 总工资:" dept[d] " 平均工资:" dept[d]/count[d]
}
}' data.csv示例5:awk条件判断
#!/bin/bash
echo "=== 使用if语句 ==="
awk '{
if ($2 >= 90) grade="优秀"
else if ($2 >= 80) grade="良好"
else if ($2 >= 70) grade="中等"
else if ($2 >= 60) grade="及格"
else grade="不及格"
print $1 " 语文成绩:" $2 " 等级:" grade
}' awk.txt
echo "=== 使用三元运算符 ==="
awk '{result=($2>=60) ? "及格" : "不及格"; print $1, result}' awk.txt示例6:awk格式化输出
#!/bin/bash
echo "=== 格式化输出 ==="
awk 'BEGIN {
printf "%-10s %-10s %-10s %-10s\n", "姓名", "语文", "数学", "英语"
printf "%-10s %-10s %-10s %-10s\n", "------", "------", "------", "------"
}
{
printf "%-10s %-10d %-10d %-10d\n", $1, $2, $3, $4
}' awk.txt
echo "=== 添加表头和数据统计 ==="
awk 'BEGIN {
print "========== 成绩统计表 =========="
print "姓名\t语文\t数学\t英语\t总分"
print "--------------------------------"
}
{
total=$2+$3+$4
printf "%s\t%d\t%d\t%d\t%d\n", $1, $2, $3, $4, total
sum_total+=total
count++
}
END {
print "--------------------------------"
printf "平均总分: %.2f\n", sum_total/count
print "================================"
}' awk.txt示例7:awk数组应用
#!/bin/bash
# 统计单词出现次数
cat > words.txt << EOF
apple banana apple orange
banana apple grape
orange banana apple
EOF
echo "=== 统计单词出现次数 ==="
awk '{
for (i=1; i<=NF; i++) {
count[$i]++
}
}
END {
for (word in count) {
print word " 出现 " count[word] " 次"
}
}' words.txt
# 去重显示
echo "=== 显示唯一值 ==="
awk '!seen[$0]++' words.txt示例8:awk实战应用(系统分析)
#!/bin/bash
# 分析系统日志
cat > access.log << EOF
192.168.1.100 - - [01/Mar/2024:10:15:23] "GET /index.html" 200 1234
192.168.1.101 - - [01/Mar/2024:10:15:25] "GET /about.html" 200 567
192.168.1.100 - - [01/Mar/2024:10:16:30] "POST /login" 401 234
192.168.1.102 - - [01/Mar/2024:10:17:45] "GET /index.html" 200 1234
192.168.1.100 - - [01/Mar/2024:10:18:12] "GET /dashboard" 200 3456
EOF
echo "=== 统计IP访问次数 ==="
awk '{count[$1]++} END {for (ip in count) print ip "访问" count[ip] "次"}' access.log
echo "=== 统计HTTP状态码 ==="
awk '{code[$9]++} END {for (c in code) print "状态码" c ":" code[c] "次"}' access.log
echo "=== 统计404错误的IP ==="
awk '$9 == 404 {print $1}' access.log | sort -u
echo "=== 计算总流量 ==="
awk '{total+=$10} END {print "总流量:" total "字节"}' access.log四、综合应用案例
案例1:提取系统信息
#!/bin/bash
# 提取系统用户信息
echo "=== 提取/etc/passwd中的用户信息 ==="
awk -F ':' '
BEGIN {
print "================================="
printf "%-15s %-10s %-10s %-20s\n", "用户名", "UID", "GID", "Shell"
print "================================="
}
{
if ($3 >= 1000 && $3 < 65534) {
printf "%-15s %-10s %-10s %-20s\n", $1, $3, $4, $7
count++
}
}
END {
print "================================="
print "普通用户数量: " count
}' /etc/passwd案例2:日志分析脚本
#!/bin/bash
# 分析nginx访问日志
LOG_FILE="/var/log/nginx/access.log" # 假设路径
# 使用sed和awk组合分析
echo "=== 最近10分钟内的错误请求 ==="
sed -n '/2024:..:..:..]/p' "$LOG_FILE" | awk '$9 >= 400'
echo "=== 最活跃的5个IP ==="
awk '{print $1}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -5
echo "=== 请求最多的5个页面 ==="
awk '{print $7}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -5案例3:数据清洗和转换
#!/bin/bash
# 将CSV转换为HTML表格
cat > employees.csv << EOF
ID,Name,Department,Salary
001,张三,技术部,8000
002,李四,市场部,7500
003,王五,技术部,9000
004,赵六,财务部,7000
EOF
awk -F ',' '
BEGIN {
print "<table border='1'>"
print "<tr><th>ID</th><th>姓名</th><th>部门</th><th>工资</th></tr>"
}
NR > 1 {
printf "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n", $1, $2, $3, $4
}
END {
print "</table>"
}' employees.csv > employees.html
echo "已生成 employees.html"案例4:监控脚本
#!/bin/bash
# 监控CPU使用率高的进程
ps aux | awk '
NR>1 {
if ($3 > 50) {
printf "警告: 进程 %s (PID: %s) CPU使用率: %s%%\n", $11, $2, $3
}
}'
# 监控磁盘使用率
df -h | awk '
$6 == "/" {
gsub(/%/, "", $5)
if ($5 > 80) {
printf "警告: 根分区使用率已达 %s%%\n", $5
}
}'五、正则表达式与文本处理器对比
| 工具 | 主要用途 | 优点 | 适用场景 |
|---|---|---|---|
| grep | 文本搜索 | 简单快速 | 查找匹配行 |
| sed | 文本编辑 | 批量处理 | 替换、删除、插入 |
| awk | 文本处理 | 功能强大 | 数据提取、统计、格式化 |
到此这篇关于Shell编程之正则表达式与文本处理器的文章就介绍到这了,更多相关Shell正则表达式与文本处理器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
scp 将数据从一台linux服务器复制到另一台linux服务器
这篇文章主要介绍了scp 将数据从一台linux服务器复制到另一台linux服务器,需要的朋友可以参考下2017-09-09


最新评论