正则表达式不是某个命令的专属能力,而是一套“描述文本规律”的语言。掌握它,grep、sed、awk这三把刀才真正锋利01 正则表达式到底是什么?
正则表达式,英文是Regular Expression,常缩写为RE / regexp。
它的作用可以简单理解为:
用一串符号,描述你想匹配的文本规律。
例如:
^root:匹配以root开头的行
txt$:匹配以txt结尾的行
^$:匹配空行
[0-9]+:匹配连续出现的数字
在 Linux 文本处理中,正则表达式经常和三剑客一起使用:
| 工具 | 常见用途 | 正则支持 |
|---|
grep | 查找、过滤文本 | 默认基础正则,-E支持扩展正则 |
sed | 替换、删除、按规则改文本 | 默认基础正则,GNU sed 可用-r/-E支持扩展正则 |
awk | 按列处理、统计、格式化输出 | 默认支持扩展正则 |
建议日常优先使用:
grep -E '正则表达式' file
或:
egrep '正则表达式' file
很多环境会给grep设置颜色别名,便于观察匹配结果:
alias grep='grep --color=auto'alias egrep='egrep --color=auto'
02 基础正则 BRE:先掌握这 9 个符号
基础正则 BRE,全称Basic Regular Expression。
grep、sed默认主要使用基础正则。入门阶段,先掌握下面这些符号。
1.^:匹配行首
^表示“以某内容开头的行”。
grep '^demo' sample.txt
含义:匹配以demo开头的行。
注意:必须使用英文半角符号。中文输入法下的符号经常会导致匹配失败。
2.$:匹配行尾
$表示“以某内容结尾的行”。
grep 'log$' sample.txt
含义:匹配以log结尾的行。
如果不确定行尾是否有隐藏字符,可以用:
cat -A sample.txt
cat -A可以显示制表符、行尾符等不可见字符,适合排查“看起来一样但匹配不上”的问题。
3.^$:匹配空行
^是行首,$是行尾。
两者连起来:
^$
表示从行首到行尾之间没有任何字符,也就是空行。
查看空行并显示行号:
grep -n '^$' sample.conf
过滤掉空行:
grep -v '^$' sample.conf
-v表示反向匹配,即“不匹配该规则的内容”。
4..:匹配任意一个字符
.表示任意一个字符,但不匹配空行。
grep 'd.mo' sample.txt
可以匹配:
demodXmod1mo
如果想看正则到底匹配到了什么,可以使用grep -o:
grep -o 'd.mo' sample.txt
-o只输出匹配到的部分,适合调试正则。
5.\:转义字符
很多符号在正则里有特殊含义,比如.表示任意字符。
如果你只想匹配真正的英文句点.,就需要转义:
grep '\.$' sample.txt
含义:匹配以英文句点结尾的行。
可以把\理解为:
脱掉特殊符号的“马甲”,让它回到普通字符本身。
6.*:前一个字符出现 0 次或多次
*表示它前面的那个字符连续出现0 次或多次。
grep 'go*d' sample.txt
可以匹配:
gdgodgoodgooood
初学时要注意:*不是“任意内容”,它只控制前一个字符。
7..*:匹配任意内容
.表示任意一个字符,*表示前一个字符出现 0 次或多次。
所以:
.*
通常可以理解为“任意内容”。这是正则里使用频率非常高的组合。
示例:
grep '^demo.*log$' sample.txt
含义:匹配以demo开头、以log结尾,中间可以是任意内容的行。
需要注意的是,.*通常具有“贪婪性”:会尽可能多地匹配内容。写脚本时要根据场景控制边界,避免匹配过宽。
8.[]:匹配中括号里的任意一个字符
[abc]表示匹配a、b、c中任意一个字符。
grep 'gr[ae]y' sample.txt
可以匹配:
graygrey
常见范围写法:
[a-z] 小写字母[A-Z] 大写字母[0-9] 数字[a-zA-Z0-9] 字母或数字
中括号本身相当于“一个字符位置”。
9.[^]:排除中括号里的字符
[^abc]表示匹配除了a、b、c之外的任意一个字符。
grep '[^0-9]' sample.txt
含义:匹配包含非数字字符的行。
注意:^在中括号外表示“行首”,在中括号内开头位置表示“取反”。位置不同,含义不同。
03 基础正则速查表
| 符号 | 含义 | 示例 |
|---|
^ | 行首 | ^demo |
$ | 行尾 | log$ |
^$ | 空行 | grep '^$' file |
. | 任意一个字符 | d.mo |
\ | 转义 | \.$ |
* | 前一个字符出现 0 次或多次 | go*d |
.* | 任意内容 | ^a.*z$ |
[] | 匹配任意一个指定字符 | [abc] |
[^] | 排除指定字符 | [^abc] |
04 扩展正则 ERE:让表达能力更强
扩展正则 ERE,全称Extended Regular Expression。
常见启用方式:
# grep 使用扩展正则grep -E '正则表达式' file# egrep 等价于 grep -Eegrep '正则表达式' file# GNU sed 使用扩展正则sed -r 's/old/new/g' file# awk 默认支持扩展正则awk '/正则表达式/' file
说明:部分系统的sed更推荐-E,GNU sed 中-r和-E都常见。
1.+:前一个字符出现 1 次或多次
+和*很像,但含义不同:
示例:
grep -E '0+' sample.txt
含义:匹配连续出现的0。
+常和[]搭配使用:
grep -E '[0-9]+' sample.txt
含义:匹配连续出现的数字。
2.|:或者
|表示“或”。
grep -E 'linux|shell' sample.txt
含义:匹配包含linux或shell的行。
如果有多个关键词:
grep -E 'ssh|http|smtp' sample-services.txt
含义:匹配包含ssh、http或smtp的行。
3.():把内容作为一个整体
小括号常用于分组,把多个字符当作一个整体。
grep -E 'demo-(log|conf)' sample.txt
可以匹配:
demo-logdemo-conf
在sed中,小括号还常用于后向引用,也叫反向引用。
示例:交换两个字段的位置:
echo 'user01:group01' |sed -r 's/^([^:]+):([^:]+)$/\2:\1/'
输出:
group01:user01
这里:
([^:]+)表示匹配一段非冒号内容
\1表示第一个括号匹配到的内容
\2表示第二个括号匹配到的内容
4.{}:精确控制出现次数
{}用来控制前一个字符出现的次数。
| 写法 | 含义 |
|---|
a{n,m} | a至少出现 n 次,最多出现 m 次 |
a{n} | a正好出现 n 次 |
a{n,} | a至少出现 n 次 |
a{,m} | a最多出现 m 次,部分工具支持情况不同 |
示例:
grep -E '[0-9]{4}' sample.txt含义:匹配连续 4 位数字。
更严格一点:
grep -E '^[0-9]{4}$' sample.txt含义:匹配整行只有 4 位数字的行。
5.?:前一个字符出现 0 次或 1 次
?表示前一个字符可有可无。
grep -E 'colou?r' sample.txt
可以匹配:
colorcolour
它适合处理“某个字符可能出现,也可能不出现”的场景。
05 扩展正则速查表
| 符号 | 含义 | 示例 |
|---|
+ | 前一个字符出现 1 次或多次 | [0-9]+ |
| | 或者 | linux|shell |
() | 分组、整体;也可用于 sed 后向引用 | (log|conf) |
{} | 控制次数 | [0-9]{4} |
? | 前一个字符出现 0 次或 1 次 | colou?r |
06 一个高频实战:过滤配置文件
日常查看配置文件时,经常会遇到大量空行和注释行。
目标:过滤掉空行和以#开头的注释行。
grep -v '^$' demo.conf |grep -v '^#'
也可以合并成一条扩展正则:
grep -Ev '^$|^#' demo.conf
如果注释前面可能有空格,可以写得更稳一点:
grep -Ev '^[[:space:]]*$|^[[:space:]]*#' demo.conf
含义:
这个写法比单纯的^$、^#更适合真实配置文件。
07 初学者最容易踩的 6 个坑
1. 中文符号和英文符号混用
正则符号必须使用英文半角符号。
例如:
^ $ . * [] () {}中文输入法下的类似符号,看起来接近,但含义完全不同。
2. 以为*表示任意内容
单独的*不是任意内容。
它的意思是:前一个字符出现 0 次或多次。
任意内容通常写成:
.*
3. 忘记基础正则和扩展正则的区别
在基础正则里,+、|、()、{}、?通常需要转义或启用扩展正则。
推荐直接使用:
grep -E 'pattern' file
这样更清晰。
4..忘记转义
.在正则里表示任意一个字符。
匹配真正的点,要写:
\.
5. 贪婪匹配范围太大
.*会尽可能多地匹配内容。
如果边界不清晰,可能会匹配超出预期。
写正则时要尽量明确开始和结束条件,例如:
grep -E '^ERROR.*timeout$' sample.log
比单纯写:
grep -E 'ERROR.*timeout' sample.log
更容易控制匹配范围。
6. 忽略不可见字符
有些文件看起来匹配不上,可能是因为行尾、Tab、空格等不可见字符。
可以用:
cat -A sample.txt
辅助排查。
08 建议的学习路线
正则表达式不建议一开始就追求“大而全”。更好的学习顺序是:
先掌握^、$、^$
再掌握.、*、.*
然后掌握[]、[^]
最后使用扩展正则:+、|、()、{}、?
结合grep -o观察匹配结果
结合真实日志、配置文件反复练习
入门阶段,记住一句话:
不要背符号,要理解“它描述了什么文本规律”。
09 小练习
假设有文件sample.txt,内容如下:
demo.logapp.conf2026error: timeout# commentuser01:group01
尝试写出命令:
匹配以demo开头的行
匹配以.conf结尾的行
找出空行
匹配连续数字
过滤掉空行和注释行
参考答案:
grep '^demo' sample.txtgrep '\.conf$' sample.txtgrep -n '^$' sample.txtgrep -E '[0-9]+' sample.txtgrep -Ev '^$|^#' sample.txt
10 最后总结
正则表达式是 Linux 文本处理的基础能力。
如果只记一张表,可以记下面这张:
| 类型 | 重点符号 |
|---|
| 基础正则 | ^$.*.*[][^]\ |
| 扩展正则 | +|(){}? |
| 常用工具 | grep -E、sed -r/-E、awk |
| 高频场景 | 过滤空行、过滤注释、提取数字、匹配日志关键字 |
正则不是用来“炫技”的,而是用来降低重复劳动的。
从今天开始,每次处理文本时都多问一句:
这个规律,能不能用一条正则描述出来?