linux shell

关注公众号 jb51net

关闭
首页 > 脚本专栏 > linux shell > Shell正则表达式与文本处理器

Shell编程之正则表达式与文本处理器示例代码

作者:刘晨鑫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.txt

3. 扩展正则表达式

扩展正则表达式添加了更多元字符,使用时需要加 -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正则表达式与文本处理器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文