一、正则表达式基础概念
正则表达式(Regular Expression,简称Regex)是用于文本模式匹配的表达式语言,广泛应用于Shell工具(如grep
、sed
、awk
)及编程语言中。其核心作用包括:
- 文本搜索:快速定位符合特定模式的字符串
- 文本替换:批量修改符合模式的文本
- 数据验证:检查输入是否符合格式要求
二、正则表达式语法分类
在Shell环境中,主要涉及两种正则语法:
- 基本正则表达式(BRE):
- 默认模式(
grep
、sed
默认使用) - 部分元字符需转义(如
\+
、\?
)
- 默认模式(
- 扩展正则表达式(ERE):
- 使用
-E
或egrep
、awk
启用 - 支持更多元字符(如
+
、?
、|
等)
- 使用
三、核心元字符速查表
元字符 | 作用 | BRE示例 | ERE示例 |
---|---|---|---|
锚定 | |||
^ | 匹配行首 | ^start | 相同 |
$ | 匹配行尾 | end$ | 相同 |
字符匹配 | |||
. | 匹配任意单个字符(除换行符) | a.c → "abc" | 相同 |
[abc] | 匹配括号内的任意字符 | gr[ae]y → "gray"/"grey" | 相同 |
[^abc] | 匹配不在括号内的字符 | [^0-9] → 非数字 | 相同 |
量词 | |||
* | 前一个元素0次或多次 | go*d → "gd"/"good" | 相同 |
\+ | 前一个元素1次或多次 | go\+d → "god"/"good" | + (无需转义) |
\? | 前一个元素0或1次 | colou\?r → "color"/"colour" | ? (无需转义) |
{n,m} | 匹配次数范围 | a\{2,4\} → "aa"/"aaa"/"aaaa" | {2,4} (无需转义) |
分组与逻辑 | |||
$...$ | 捕获分组 | $ab$\+ → "abab" | (...) (无需转义) |
| | 逻辑或 | 不支持 | apple|banana |
特殊序列 | |||
\d | 数字(部分工具支持) | 需工具支持 | [0-9] 的简写 |
\s | 空白字符 | 需工具支持 | [ \t\n\r] 的简写 |
\b | 单词边界 | \bword\b → 独立单词 | 相同 |
四、Shell工具中的正则应用
1. grep
# 基本正则(默认)
grep 'error: [0-9]\+' log.txt # 匹配"error: 123"格式
# 扩展正则(-E或egrep)
egrep 'ERROR|WARNING' log.txt # 匹配ERROR或WARNING
grep -E '^[A-Z]{3}-\d{4}' codes.txt # 匹配如ABC-1234的代码
2. sed
# 替换操作(使用基本正则)
sed 's/$http:\/\/$example/\1newexample/' file.txt
# 扩展正则(-r选项)
sed -r 's/(\d{4})-(\d{2})/\2\/\1/' dates.txt # 2023-09 → 09/2023
3. awk
# 匹配整行
awk '/^192\.168/ {print $1}' access.log # 匹配以IP开头的行
# 匹配字段
awk '$2 ~ /^[A-Z][a-z]+$/ {print $0}' data.csv # 第2列是首字母大写的单词
4. find
# 按正则匹配文件名
find . -regex '.*/backup_[0-9]{8}\.tar\.gz$' # 查找backup_20230901.tar.gz
五、常用模式示例
1. 邮箱地址验证
grep -E '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$' emails.txt
2. 匹配IPv4地址
egrep '((25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})' log.txt
3. 提取日期时间
# 匹配YYYY-MM-DD HH:MM:SS格式
sed -nE 's/.*([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}).*/\1/p' logfile
4. 删除HTML标签
sed 's/<[^>]*>//g' webpage.html
5、基本匹配
-
匹配包含特定字符串的行
- 查找包含“root”字符串的行:
cat /etc/passwd | grep root
- 查找包含“root”字符串的行:
-
匹配以特定字符开头的行
- 查找以“a”字符开头的行:
cat /etc/passwd | grep ^a
- 查找以“a”字符开头的行:
-
匹配以特定字符结尾的行
- 查找以“e”字符结尾的行:
cat /etc/passwd | grep e$
- 查找以“e”字符结尾的行:
-
匹配任意单个字符
- 查找以“r”开头,“t”结尾,中间包含任意两个字符的行:
cat /etc/passwd | grep r..t
- 查找以“r”开头,“t”结尾,中间包含任意两个字符的行:
-
匹配特定范围内的字符
-
查找包含数字6或8的行(这里使用了方括号表示字符范围):
cat /some/file | grep [68]
-
查找包含一个0到9之间的数字的行:
cat /some/file | grep [0-9]
-
6、特殊字符和转义
-
匹配任意长度的数字字符串
- 使用星号(*)匹配任意长度的数字字符串:
cat /some/file | grep [0-9]*
- 使用星号(*)匹配任意长度的数字字符串:
-
匹配特定字符并转义
- 查找包含“”符号的行(需要使用反斜杠进行转义):‘cat/scripts/ntest.sh∣grep′ '`
-
匹配不包含特定字符串的行
- 使用grep的-v选项查找不包含“QP”字符串的行:
ls -lR ./OutResult/ | grep -v 'QP'
- 使用grep的-v选项查找不包含“QP”字符串的行:
7、分组和预搜索
-
分组匹配
- 使用圆括号进行分组匹配,并提取文本中的一部分内容。例如,查找以“a”开头,“in”结尾,中间包含任意字符的行,并提取中间的内容:
cat /etc/passwd | grep '^a.*in$'
(注意,这里并没有直接提取中间内容,但分组的概念可以用于更复杂的正则表达式中)
- 使用圆括号进行分组匹配,并提取文本中的一部分内容。例如,查找以“a”开头,“in”结尾,中间包含任意字符的行,并提取中间的内容:
-
正向预搜索
- 使用正向预搜索(?=pattern)查找不匹配特定模式的字符串开始处。例如,查找不以“QP”开头的以“svac2”结尾的行:
ls -lR | grep -E '((?!QP).).*svac2$'
- 使用正向预搜索(?=pattern)查找不匹配特定模式的字符串开始处。例如,查找不以“QP”开头的以“svac2”结尾的行:
8、实际案例
-
归档脚本中的正则表达式
- 在归档脚本中,可以使用正则表达式来匹配和过滤文件名。例如,根据日期模式匹配归档文件名:
FILE=archive_${DIR_NAME}_$(date +%y%m%d).tar.gz
- 在归档脚本中,可以使用正则表达式来匹配和过滤文件名。例如,根据日期模式匹配归档文件名:
-
使用awk和cut进行文本处理
-
结合awk和cut命令,使用正则表达式进行文本处理。例如,使用awk提取passwd文件中以“root”开头的行的第七列:
cat /etc/passwd | awk -F ":" '/^root/ {print $7}'
-
使用cut命令从文件中剪切数据。例如,从passwd文件中提取以“bash”结尾的行的第一、六、七列:
cat /etc/passwd | grep bash | cut -d ":" -f 1,6,7
-
-
匹配以
hello
开头的行:grep '^hello' filename
-
匹配以
world
结尾的行:grep 'world$' filename
-
匹配包含
a
或b
的行(注意:在基本正则表达式中,|
需要通过egrep
或grep -E
来支持):egrep 'a|b' filename # 或者 grep -E 'a|b' filename
-
匹配包含数字的行:
grep '[0-9]' filename
-
匹配不包含字母的行(即只包含数字、空格或其他非字母字符):
grep '^[^a-zA-Z]*$' filename
-
匹配以
a
开头,后面跟着任意数量的字符,再以z
结尾的行:grep '^a.*z$' filename
六、调试与优化技巧
-
在线测试工具:
- RegExr
- Regex101
-
调试方法:
# 分阶段测试正则组件 echo "test123" | grep '^[a-z]\+[0-9]\+$' # 使用echo验证替换效果 echo "price: $5.99" | sed 's/\$$[0-9]\+$\.$[0-9]\+$/\1元\2角/'
-
性能优化:
- 避免使用
.*
的贪婪匹配 - 优先使用具体字符集(如
[0-9]
代替\d
) - 使用锚定符缩小匹配范围
- 避免使用
七、注意事项
-
工具差异:
awk
默认使用ERE且不支持\d
grep -P
启用PCRE(Perl兼容正则,需GNU grep)
-
转义规则:
- Shell本身会解析反斜杠,需双重转义:
# 匹配单个反斜杠需要写成四个反斜杠 echo "path: C:\\Windows" | grep 'C:\\\\Windows'
- Shell本身会解析反斜杠,需双重转义:
-
可读性维护:
- 复杂正则添加注释(部分工具支持
(?x)
忽略空格和注释):grep -P '(?x)^ \d{3} # 前三位数字 -? # 可选分隔符 \d{2} # 中间两位 -? # 可选分隔符 \d{4} # 最后四位 $' ssn.txt
- 复杂正则添加注释(部分工具支持
通过掌握这些正则表达式技巧,可以高效处理以下场景:
- 日志分析(提取关键错误信息)
- 数据清洗(格式化不规则数据)
- 配置管理(批量修改配置文件)
- 输入验证(检查用户输入格式)
建议结合具体工具手册(man 7 regex
)深入学习正则表达式的高级特性。