27人参与 • 2026-03-04 • 正则表达式
正则表达式(regular expression, regex)是 shell 编程中处理文本的核心工具,配合 grep、sed、awk 等工具可实现强大的文本查找、替换、提取功能。本教程从基础到进阶,结合大量可直接运行的示例,帮你彻底掌握 shell 正则表达式。
shell 中主要使用三种正则规范,不同工具支持的类型不同:
| 类型 | 说明 | 支持工具 |
|---|---|---|
| 基本正则(bre) | 基础元字符,部分元字符需转义 | grep(默认)、sed(默认) |
| 扩展正则(ere) | 更多元字符,无需额外转义 | grep -e、sed -e、awk |
| perl 兼容正则(pcre) | 功能最强,支持非贪婪匹配等高级特性 | grep -p |
grep:文本查找(global regular expression print)sed:文本替换、编辑(stream editor)awk:文本处理、数据分析(aho-weinberger-kernighan)| 元字符 | 功能说明 | 示例 | 示例解释 |
|---|---|---|---|
^ | 匹配行首 | grep '^root' /etc/passwd | 匹配以root开头的行 |
$ | 匹配行尾 | grep 'bash$' /etc/passwd | 匹配以bash结尾的行 |
. | 匹配任意单个字符(除换行) | grep 'r..t' /etc/passwd | 匹配r和t之间有 2 个任意字符的行(如root、rbtx) |
* | 匹配前一个字符 0 次或多次 | grep 'ro*t' /etc/passwd | 匹配rt、rot、root、rooot等 |
[] | 匹配括号内任意单个字符 | grep 'r[ao]t' file.txt | 匹配rat或rot |
[^] | 匹配不在括号内的任意字符 | grep 'r[^ao]t' file.txt | 匹配rbt、rct等,但不匹配rat、rot |
\ | 转义元字符,使其失去特殊含义 | grep 'www\.example\.com' file.txt | 匹配字面量www.example.com(.被转义) |
在 bre 中,以下元字符必须加 \ 转义才生效:
| 元字符(转义后) | 功能说明 | 示例 | |
|---|---|---|---|
\{n\} | 匹配前一个字符恰好n次 | grep 'ro\{2\}t' /etc/passwd | 匹配root(o恰好 2 次) |
\{n,\} | 匹配前一个字符至少n次 | grep 'ro\{2,\}t' file.txt | 匹配root、rooot等 |
\{n,m\} | 匹配前一个字符n到m次 | grep 'ro\{1,3\}t' file.txt | 匹配rot、root、rooot |
使用 grep -e、sed -e 或 awk 时,元字符无需转义,功能更强大。
| 元字符 | 功能说明 | 示例(用grep -e) | |||
|---|---|---|---|---|---|
+ | 匹配前一个字符 1 次或多次 | grep -e 'ro+t' file.txt | 匹配rot、root、rooot(不匹配rt) | ||
? | 匹配前一个字符 0 次或 1 次 | grep -e 'ro?t' file.txt | 匹配rt或rot | ||
| ` | ` | 或逻辑,匹配左右任意一个 | `grep -e 'root | admin' /etc/passwd` | 匹配包含root或admin的行 |
() | 分组,将多个字符视为整体 | grep -e '(root)+' file.txt | 匹配root、rootroot等 | ||
{n} | 匹配前一个字符恰好n次(无需转义) | grep -e 'ro{2}t' file.txt | 匹配root | ||
{n,} | 匹配前一个字符至少n次 | grep -e 'ro{2,}t' file.txt | 匹配root、rooot等 | ||
{n,m} | 匹配前一个字符n到m次 | grep -e 'ro{1,3}t' file.txt | 匹配rot、root、rooot |
为了兼容不同字符集(如中文),shell 提供了 posix 字符类,需用 [[]] 包裹:
| 字符类 | 说明 | 等价于(ascii) | |
|---|---|---|---|
[:alnum:] | 字母和数字 | [a-za-z0-9] | |
[:alpha:] | 字母 | [a-za-z] | |
[:digit:] | 数字 | [0-9] | |
[:lower:] | 小写字母 | [a-z] | |
[:upper:] | 大写字母 | [a-z] | |
[:space:] | 空白字符(空格、制表符等) | [ \t\n\r\f\v] | |
[:punct:] | 标点符号 | [!\"#$%&'()*+,-./:;<=>?@[\\\]^_{ | }~]` |
示例:匹配包含数字的行
grep '[[:digit:]]' file.txt
# 查找包含"error"的行(忽略大小写) grep -i 'error' log.txt # 查找不包含"debug"的行 grep -v 'debug' log.txt # 显示匹配行的行号 grep -n 'root' /etc/passwd # 递归查找当前目录下所有文件中的"todo" grep -r 'todo' .
# 查找以"202"开头的年份(如2020、2021...2029)
grep -e '^202[0-9]' dates.txt
# 查找邮箱(简化版)
grep -e '[a-za-z0-9._%+-]+@[a-za-z0-9.-]+\.[a-za-z]{2,}' emails.txtsed 默认使用 bre,加 -e 启用 ere。
# 将文件中所有"apple"替换为"orange"(直接修改文件:加-i) sed 's/apple/orange/g' file.txt > new_file.txt sed -i 's/apple/orange/g' file.txt # 直接修改原文件 # 只替换第2次出现的"apple" sed 's/apple/orange/2' file.txt
# 将"root:x:0:0:root:/root:/bin/bash"改为"user: root, shell: /bin/bash" # 分组\1匹配root,\2匹配/bin/bash sed -e 's/^([a-z]+):.*:([^:]+)$/user: \1, shell: \2/' /etc/passwd # 删除空行 sed '/^$/d' file.txt # 删除以#开头的注释行 sed '/^#/d' file.txt
awk 默认使用 ere,功能极其强大。
# 打印/etc/passwd的第1列(用户名)和第7列(shell)
awk -f: '{print $1, $7}' /etc/passwd
# 打印第3列(uid)大于1000的行
awk -f: '$3 > 1000' /etc/passwd# 打印以"r"开头的用户名及其shell
awk -f: '$1 ~ /^r/ {print $1, $7}' /etc/passwd
# 统计日志中"error"出现的次数
awk '/error/ {count++} end {print "error count:", count}' log.txt
# 提取ip地址(简化版)
awk '/([0-9]{1,3}\.){3}[0-9]{1,3}/ {print $0}' access.loggrep -e '^1[3-9][0-9]{9}$' phones.txtgrep -e '([0-9]{1,3}\.){3}[0-9]{1,3}' ips.txtgrep -e '^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$' dates.txtgrep -eo 'href="[^" rel="external nofollow" ]+"' index.html | sed -e 's/href="([^" rel="external nofollow" ]+)"/\1/'
+、?、|、()、{} 需转义,ere 中无需转义。' 和双引号 " 的区别:单引号内的元字符不会被 shell 解析,推荐使用单引号包裹正则。a.*b 匹配 aabab 中的整个字符串。grep -p),如 a.*?b 匹配 aab。[:alpha:] 匹配中文字母)。到此这篇关于shell正则表达式实战:从入门到精通的文章就介绍到这了,更多相关shell正则表达式内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论