正则表达式与文本处理三剑客(grep, sed, awk)
一、正则表达式核心知识
1. 正则表达式类型对比
| 类型 | 标识符 | 特点 | 示例 |
|---|---|---|---|
| 基础正则 (BRE) | 默认 | 元字符需转义(如\+, \() |
grep "a\+" file |
| 扩展正则 (ERE) | -E |
元字符免转义(如+, () |
grep -E "a+" file |
| Perl正则 (PCRE) | -P |
支持特殊字符类(\d, \w) |
grep -P "\d+" file |
2. 正则表达式元素详解
单字符匹配
| 表达式 | 功能 | 示例 |
|---|---|---|
. |
匹配任意单个字符 | a.c → abc, adc |
[abc] |
匹配指定字符之一 | [aeiou] → a, e |
[^abc] |
匹配非指定字符 | [^0-9] → a, B |
\d |
数字(仅PCRE) | \d\d → 12, 34 |
\w |
单词字符(仅PCRE) | \w+ → hello, world |
量词匹配
| 量词 | 功能 | BRE | ERE/PCRE |
|---|---|---|---|
* |
0次或多次 | a* |
同左 |
+ |
1次或多次 | a\+ |
a+ |
? |
0次或1次 | a\? |
a? |
{n} |
恰好n次 | a\{3\} |
a{3} |
{n,} |
至少n次 | a\{3,\} |
a{3,} |
{n,m} |
n到m次 | a\{2,4\} |
a{2,4} |
位置锚定
| 锚点 | 功能 | 示例 |
|---|---|---|
^ |
行首 | ^start |
$ |
行尾 | end$ |
\< |
词首 | \<word |
\> |
词尾 | word\> |
\b |
单词边界(仅PCRE) | \bword\b |
分组与引用
| 表达式 | 功能 | 示例 |
|---|---|---|
( ) |
分组 | (abc)+ → abcabc |
\1, \2... |
引用分组 | (f)or\1 → forf |
(?: ) |
非捕获分组(PCRE) | (?:ab)+ → abab |
(?= ) |
正向先行断言(PCRE) | Windows(?=10) → Windows10 |
(?<= ) |
正向后行断言(PCRE) | (?<=MS)Windows → MSWindows |
二、grep文本搜索大师
常用选项速查表
| 选项 | 功能 | 示例 |
|---|---|---|
-i |
忽略大小写 | grep -i "error" log.txt |
-v |
反向匹配 | grep -v "debug" app.log |
-r |
递归搜索目录 | grep -r "TODO" src/ |
-l |
只显示文件名 | grep -l "pattern" *.log |
-c |
统计匹配行数 | grep -c "success" report.txt |
-n |
显示行号 | grep -n "warning" messages.log |
-o |
只显示匹配部分 | grep -o "http://.*" access.log |
-A N |
显示匹配后N行 | grep -A 2 "Exception" error.log |
-B N |
显示匹配前N行 | grep -B 1 "fatal" crash.log |
-C N |
显示匹配前后各N行 | grep -C 3 "critical" system.log |
-P |
使用Perl正则 | grep -P "\d{3}-\d{4}" file |
-E |
使用扩展正则 | `grep -E "apple |
实战案例
-
查找IP地址:
grep -P '((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])' access.log -
统计错误类型:
grep -c "ERROR" app.log grep -c "WARNING" app.log -
提取URL参数:
grep -oP 'https?://\K[^/?]+' access.log
三、sed流编辑器
sed命令结构
sed [选项] '范围 命令' 文件
常用选项
| 选项 | 功能 | 示例 |
|---|---|---|
-n |
禁止默认输出 | sed -n 'p' file |
-e |
多命令编辑 | sed -e 's/a/b/' -e 's/c/d/' |
-i[.SUF] |
直接修改文件(可备份) | sed -i.bak 's/old/new/' file |
-r |
使用扩展正则 | sed -r 's/(ab)+/cd/' file |
范围指定
| 范围 | 含义 | 示例 |
|---|---|---|
10 |
第10行 | sed '10d' file |
10,20 |
10到20行 | sed '10,20s/a/b/' |
/start/,/end/ |
从start到end的行 | sed '/BEGIN/,/END/p' |
$ |
最后一行 | sed '$s/$/END/' |
1~2 |
奇数行 | sed '1~2d' file |
2~3 |
从第2行开始每隔3行 | sed '2~3s/a/b/' |
常用命令
| 命令 | 功能 | 示例 |
|---|---|---|
s/// |
替换文本 | sed 's/old/new/g' file |
p |
打印行 | sed -n '/pattern/p' file |
d |
删除行 | sed '/debug/d' app.log |
a\text |
行后追加 | sed '3a\New Line' file |
i\text |
行前插入 | sed '/header/i\Title' file |
c\text |
替换整行 | sed '5c\Replacement' file |
y/abc/ABC/ |
字符转换 | sed 'y/abc/ABC/' file |
r file |
读取文件插入 | sed '/pattern/r data.txt' |
w file |
写入匹配行到文件 | sed '/pattern/w output.txt' |
实战案例
-
批量替换:
sed -i.bak 's/http:\/\/old-site/https:\/\/new-site/g' *.html -
删除注释和空行:
sed -e '/^#/d' -e '/^$/d' config.ini -
添加多行内容:
sed '/Database Settings/a\ DB_HOST=localhost\ DB_PORT=3306\ DB_USER=admin' config.cfg
四、awk文本处理语言
awk处理模型
awk 'BEGIN {初始化} 模式 {动作} END {收尾}' 文件
内置变量
| 变量 | 含义 | 示例 |
|---|---|---|
$0 |
整行内容 | awk '{print $0}' file |
$1-$N |
第N列字段 | awk '{print $2}' file |
NF |
当前行字段数 | awk 'NF>5{print}' file |
NR |
当前行号 | awk 'NR==2{print}' file |
FS |
输入字段分隔符 | awk -F: '{print $1}' |
OFS |
输出字段分隔符 | `awk ‘BEGIN{OFS=" |
RS |
输入记录分隔符 | awk 'BEGIN{RS=";"}{print}' |
ORS |
输出记录分隔符 | awk 'BEGIN{ORS="\n\n"}{print}' |
实战案例
-
提取特定列:
awk -F: '{print $1, $3}' /etc/passwd -
统计文件信息:
awk '{chars += length($0); words += NF} END{print "Lines:", NR, "Words:", words, "Chars:", chars}' file.txt -
HTTP状态码统计:
awk '{status[$9]++} END{for(s in status) print s, status[s]}' access.log | sort -nr -
计算1-100奇数和:
seq 100 | awk '{if($1%2) sum+=$1} END{print sum}'
五、通配符 vs 正则表达式
| 特性 | 通配符 | 正则表达式 | 示例对比 |
|---|---|---|---|
| 用途 | 文件名匹配 | 文本内容匹配 | ls *.txt vs grep ".*txt" |
| 命令 | ls, cp, find |
grep, sed, awk |
|
* |
任意字符序列 | 前元素0次或多次 | *.log vs .*\.log |
? |
单个字符 | 前元素0次或1次 | file?.txt vs file.\.txt |
[] |
字符集合 | 字符集合 | [abc]* vs [abc].* |
. |
字面点字符 | 任意字符 | file.txt vs file\.txt |
^ |
无特殊含义 | 行首 | – vs ^start |
$ |
无特殊含义 | 行尾 | – vs end$ |
{} |
扩展序列 | 需转义 | {1..10} vs \{1,10\} |
六、高级技巧合集
1. 组合使用三剑客
# 查找访问量最高的5个IP
grep -oP '\d+\.\d+\.\d+\.\d+' access.log | sort | uniq -c | sort -nr | head -5
# 批量重命名文件
ls *.jpg | awk '{print "mv", $0, "image_" NR ".jpg"}' | bash
2. 实用单行命令
# 删除文件中的空行
sed '/^$/d' file.txt
# 在每行行首添加行号
awk '{print NR, $0}' file.txt
# 提取XML标签内容
grep -oP '<title>\K[^<]+' page.html
# 转换CSV为TSV
sed 's/,/\t/g' data.csv
3. 性能优化技巧
# 处理大文件时使用LC_ALL=C加速
LC_ALL=C grep "pattern" huge.log
# 使用mawk代替gawk加速处理
sudo apt install mawk
mawk '{print $1}' bigfile.txt
4. 安全注意事项
# 使用备份进行原地编辑
sed -i.bak 's/password/******/' config.txt
# 测试后再执行
sed 's/danger/safe/g' file | less # 确认无误后再加-i
总结
-
正则选择:
- 简单匹配 → 基础正则
- 复杂逻辑 → Perl正则
- 兼容性好 → 扩展正则
-
工具选用:
- 文本搜索 →
grep - 流编辑 →
sed - 数据处理 →
awk
- 文本搜索 →
-
高效组合:
# 分析Nginx访问日志 awk '{print $1}' access.log | sort | uniq -c | sort -nr | head -10 # 批量重命名文件 ls | awk '{print "mv", $0, tolower($0)}' | bash -
避免陷阱:
- 通配符用于文件名,正则用于文本内容
- 使用
-i前务必备份或测试 - 处理特殊字符注意转义