Linux 正則表達式詳解(基礎 + 擴展 + 實操)
正則表達式(Regular Expression,簡稱 RE)是 Linux 文本處理的核心工具,用于定義字符匹配模式,配合 grep
、sed
、awk
等工具可實現文本過濾、查找、替換等操作。本文將從概念、基礎正則、擴展正則、特殊字符組四個維度,結合實操案例完整講解
一、正則表達式概述
1. 核心概念
正則表達式是模式模板,Linux 工具通過該模板對數據流進行 “匹配篩選”:
- 匹配的數據:被工具接受并進一步處理(如輸出、替換)
- 不匹配的數據:被直接濾除
本質:通過 “普通字符 + 元字符” 的組合,描述字符串的排列規則,實現對文本的分割、匹配、查找、替換
2. 構成與作用
構成部分 | 說明 | 示例 |
---|---|---|
普通字符 | 無特殊含義的字符(字母、數字、標點) | a 、1 、! 、- |
元字符 | 具有特殊匹配規則的專用字符 | ^ 、$ 、* 、[ ] |
核心作用:判斷字符串是否符合指定格式(如 “是否為手機號”“是否為郵箱”),或從文本中提取特定格式的內容(如 “提取所有 IP 地址”)
3. 可實現的核心目標
- 匹配驗證:判斷字符串是否符合正則模式(如 “驗證一行文本是否以
#
開頭”) - 內容提取:從復雜文本中篩選出符合模式的部分(如 “從日志中提取所有錯誤代碼”)
二、基礎正則(Basic Regular Expression,BRE)
基礎正則是正則的 “核心子集”,支持 grep
、sed
(基礎模式)、awk
等工具,核心是掌握元字符的匹配規則
1. 基礎正則核心元字符表
元字符 | 功能描述 | 示例 | 匹配效果 |
---|---|---|---|
\ | 轉義字符:將特殊字符還原為普通字符 | \$ 、\! 、\n | 匹配 $ 、! 、換行符 |
^ | 匹配 “字符串開頭” 的位置 | ^a 、^# | 匹配以 a 開頭、以 # 開頭的行 |
$ | 匹配 “字符串結尾” 的位置 | word$ 、3$ | 匹配以 word 結尾、以 3 結尾的行 |
^$ | 匹配 “空行”(開頭到結尾無任何字符) | grep "^$" file.txt | 篩選文件中的所有空行 |
. | 匹配 “除換行符(\n)外的任意 1 個字符” | lo.k 、l..k | loak (1 個字符)、look (2 個字符) |
* | 匹配 “前面 1 個字符出現 0 次或多次” | lo*k | lk (o 出現 0 次)、lok (o1 次)、look (o2 次) |
[list] | 匹配 “list 列表中的任意 1 個字符” | go[ola]d 、[a-z0-9] | gold /goal /god 、任意小寫字母或數字 |
[^list] | 匹配 “非 list 列表中的任意 1 個字符” | [^0-9] 、[^a-z] | 非數字、非小寫字母 |
\{n\} | 匹配 “前面 1 個字符出現恰好 n 次” | lo\{2\}k 、[0-9]\{2\} | look (o2 次)、任意 2 位數字 |
\{n,\} | 匹配 “前面 1 個字符出現至少 n 次” | lo\{2,\}k 、[0-9]\{3,\} | look (o2 次)、loook (o3 次)、3 位及以上數字 |
\{n,m\} | 匹配 “前面 1 個字符出現n~m 次” | lo\{2,3\}k | look (o2 次)、loook (o3 次) |
注意:基礎正則中,
{n}
/{n,}
/{n,m}
必須加轉義符\
,否則會被當作普通字符處理
2. 基礎正則實操案例
以下案例基于測試文件 a.txt
/b.txt
/c.txt
,先定義測試文件內容:
[root@syf ~]# vim a.txt
lk
lok
look
loook
looooook
loooooaaak
looooooook
abbbbcd
abbbbcd666
ooooloooook
oooooolk
aoblck
~
[root@syf ~]# vim b.txt
aaabd
cdd
cdc
cdd
~
[root@syf ~]# vim c.txt
lok
lo12k
lo1k
loAk
loBk
look
loak
lodk
abcd
1234
~
案例 1:*
匹配 “前面字符 0 次或多次”
# 匹配 "lo*k":o出現0次(lk)、1次(lok)、多次(look等)
[root@syf ~]# grep "lo*k" a.txt
lk # o出現0次
lok # o出現1次
look # o出現2次
loook # o出現3次
looooook # o出現5次
looooooook # o出現7次
ooooloooook # 中間含多個o
oooooolk # o出現6次# 匹配 "loo*k":o至少出現1次(排除lk)
[root@syf ~]# grep "loo*k" a.txt
lok # o出現1次
look # o出現2次
loook # o出現3次
looooook # o出現5次
looooooook # o出現7次
ooooloooook # 中間含多個o
案例 2:.
匹配 “任意 1 個字符”
# 匹配 "lo.*k":o后接“任意字符(0次或多次)”+k(.*表示任意字符任意次)
[root@syf ~]# grep "lo.*k" a.txt
lok # o后接0個字符
look # o后接1個o
loook # o后接2個o
looooook # o后接4個o
loooooaaak # o后接3個o+2個a
looooooook # o后接5個o
ooooloooook # 前面有o,中間含多個o# 匹配 "lo.k":o后接“恰好1個字符”+k
[root@syf ~]# grep "lo.k" a.txt
look # o后接1個o(lo+o+k)# 匹配 "l..k":l后接“恰好2個字符”+k
[root@syf ~]# grep "l..k" a.txt
look # l后接2個o(l+oo+k)
案例 3:\{n\}
/\{n,\}
/\{n,m\}
匹配 “固定次數”
# 匹配 "lo\{2\}k":o恰好出現2次
[root@syf ~]# grep "lo\{2\}k" a.txt
look # o出現2次# 匹配 "lo\{3\}k":o恰好出現3次
[root@syf ~]# grep "lo\{3\}k" a.txt
loook # o出現3次# 匹配 "lo\{3,\}k":o至少出現3次
[root@syf ~]# grep "lo\{3,\}k" a.txt
loook # o出現3次
looooook # o出現5次
looooooook # o出現7次
ooooloooook # 中間o出現5次# 匹配 "lo\{3,5\}k":o出現3~5次
[root@syf ~]# grep "lo\{3,5\}k" a.txt
loook # o出現3次
ooooloooook # 中間o出現5次(符合3~5次)
案例 4:^
/$
/^$
匹配 “開頭 / 結尾 / 空行”
# 匹配 "^c":以c開頭的行
[root@syf ~]# grep "^c" b.txt
cdd
cdc
cdd# 匹配 "d$":以d結尾的行
[root@syf ~]# grep "d$" b.txt
abd
cdd
cdd# 匹配 "^$":空行(輸出為空行,對應b.txt中的空行)
[root@syf ~]# grep "^$" b.txt
(此處輸出1行空行)
案例 5:[list]
/[^list]
匹配 “指定 / 非指定字符”
# 匹配 "lo[a-zA-Z0-9]k":o后接1個“字母/數字”+k
[root@syf ~]# grep "lo[a-zA-Z0-9]k" c.txt
lo1k # o后接數字1
loAk # o后接大寫A
loBk # o后接大寫B
look # o后接小寫o
loak # o后接小寫a
lodk # o后接小寫d# 匹配 "lo[ABo]k":o后接A/B/o中的任意1個
[root@syf ~]# grep "lo[ABo]k" c.txt
loAk # A
loBk # B
look # o# 匹配 "lo[^a-zA-Z]k":o后接“非字母”(即數字/符號)
[root@syf ~]# grep "lo[^a-zA-Z]k" c.txt
lo1k # 非字母(數字1)# 匹配 "[^a-zA-Z]":包含“非字母”的行(數字/符號)
[root@syf ~]# grep "[^a-zA-Z]" c.txt
lo12k # 含數字1、2
lo1k # 含數字1
1234 # 全是數字
三、擴展正則(Extended Regular Expression,ERE)
擴展正則是基礎正則的 “增強版”,新增了 +
、?
、()
、|
等元字符,且 {n}
/{n,}
/{n,m}
無需轉義。支持工具:egrep
(grep -E
)、awk
、sed -r
(擴展模式)
1. 擴展正則核心元字符表
元字符 | 功能描述 | 示例 | 匹配效果 | ||
---|---|---|---|---|---|
+ | 匹配 “前面 1 個字符出現 1 次或多次”(比* 嚴格) | lo+k | 匹配 lok (1 次)、look (2 次),不匹配 lk | ||
? | 匹配 “前面 1 個字符出現 0 次或 1 次”(最多 1 次) | lo?k | 僅匹配 lk (0 次)、lok (1 次) | ||
() | 將括號內的字符視為 “1 個整體”(分組) | l(oo)+k | 匹配 look (oo1 次)、looook (oo2 次) | ||
` | ` | 邏輯 “或”:匹配多個模式中的任意 1 個 | `l(oo | ab)k` | 匹配 look (oo)、labk (ab) |
{n} | 同基礎正則 \{n\} ,無需轉義 | lo{2}k | 匹配 look (o2 次) | ||
{n,} | 同基礎正則 \{n,\} ,無需轉義 | lo{3,}k | 匹配 loook (o3 次)及以上 | ||
{n,m} | 同基礎正則 \{n,m\} ,無需轉義 | lo{3,5}k | 匹配 loook (o3 次)~looooook (o5 次) |
2. 擴展正則實操案例(基于 a.txt
)
案例 1:+
匹配 “前面字符 1 次及以上”
# 匹配 "lo+k":o至少1次(排除lk)
[root@syf ~]# egrep "lo+k" a.txt
lok # o1次
look # o2次
loook # o3次
looooook # o5次
looooooook # o7次
ooooloooook # 中間o5次
案例 2:?
匹配 “前面字符 0 次或 1 次”
# 匹配 "lo?k":o最多1次(僅lk、lok)
[root@syf ~]# egrep "lo?k" a.txt
lk # o0次
lok # o1次
oooooolk # 前面o6次,最后o0次(符合lo?k)
案例 3:()
分組匹配 “整體重復”
# 匹配 "l(oo)+k":將"oo"視為整體,至少重復1次
look # "oo"重復1次(l+oo+k)
looooook # "oo"重復2次(l+oo+oo+k)
looooooook # "oo"重復3次(l+oo+oo+oo+k)
案例 4:|
邏輯 “或” 匹配多模式
# 先添加測試行 "labk" 到 a.txt
[root@syf ~]# echo "labk" >> a.txt# 匹配 "l(oo|ab)k":匹配 "loo k" 或 "lab k"
[root@syf ~]# egrep "l(oo|ab)+k" a.txt
look # 匹配 "oo"
looooook # 匹配 "oo"(重復2次)
looooooook # 匹配 "oo"(重復3次)
labk # 匹配 "ab"
案例 5:{n}
/{n,}
/{n,m}
無需轉義
# 匹配 "lo{3}k":o恰好3次(無需轉義{3})
[root@syf ~]# egrep "lo{3}k" a.txt
loook # o3次# 匹配 "lo{3,}k":o至少3次
[root@syf ~]# egrep "lo{3,}k" a.txt
loook # o3次
looooook # o5次
looooooook # o7次
ooooloooook # 中間o5次# 匹配 "lo{3,5}k":o3~5次
[root@syf ~]# egrep "lo{3,5}k" a.txt
loook # o3次
ooooloooook # 中間o5次
四、特殊字符組(字符類)
為簡化正則書寫,Linux 提供了預定義字符組(又稱 “字符類”),等價于基礎正則中的某些字符集合,更易記憶和跨平臺(避免不同編碼的字符范圍問題)
特殊字符組表
字符組 | 等價寫法 | 描述 | 應用場景 |
---|---|---|---|
[[:alpha:]] | [a-zA-Z] | 匹配任意字母(大寫 + 小寫) | 提取純字母內容 |
[[:alnum:]] | [a-zA-Z0-9] | 匹配任意字母或數字 | 提取賬號、ID(僅字母數字) |
[[:blank:]] | [ \t] | 匹配空格或 Tab 鍵 | 查找含空格 / Tab 的行 |
[[:digit:]] | [0-9] | 匹配任意數字(0~9) | 提取手機號、IP 地址中的數字部分 |
[[:lower:]] | [a-z] | 匹配任意小寫字母 | 轉換為大寫前的篩選 |
[[:upper:]] | [A-Z] | 匹配任意大寫字母 | 轉換為小寫前的篩選 |
[[:print:]] | - | 匹配任意可打印字符(含空格、標點) | 排除不可見字符(如控制字符) |
[[:punct:]] | [!\"#$%&...] | 匹配任意標點符號 | 提取含標點的句子 |
[[:space:]] | [ \t\n\r...] | 匹配任意空白字符(空格、Tab、換行等) | 查找含空白字符的行 |
實操示例
# 1. 匹配含數字的行([[:digit:]] 等價于 [0-9])
[root@syf ~]# grep "[[:digit:]]" c.txt
lo12k
lo1k
1234# 2. 匹配純字母的行([[:alpha:]]+ 表示“字母出現1次及以上”)
[root@syf ~]# egrep "^[[:alpha:]]+$" c.txt
lok
loAk
loBk
look
loak
lodk
abcd# 3. 匹配含標點的行([[:punct:]])
[root@syf ~]# echo 'Hello,World!' > d.txt
[root@syf ~]# grep "[[:punct:]]" d.txt
Hello, World! # 含逗號和感嘆號
核心知識點總結
- 基礎正則 vs 擴展正則:
- 基礎正則:
{n}
/{n,}
/{n,m}
需轉義(\{n\}
),無+
/?
/()
/|
- 擴展正則:
{n}
無需轉義,支持+
/?
/()
/|
,工具用egrep
/sed -r
/awk
- 基礎正則:
- 元字符優先級:
- 分組
()
> 次數*
/+
/?
/{n}
> 位置^
/$
> 邏輯|
- 分組
- 特殊字符組:優先使用
[[:digit:]]
而非[0-9]
,跨平臺更穩定