Linux 正則表達式
-
定義:正則表達式是一種pattern(模式),用于與待搜索字符串匹配,以查找一個或多個目標字符串。
-
組成:自成體系,由兩類字符構成
-
普通字符:未被顯式指定為元字符的所有可打印和不可打印字符,包括大小寫字母、數字、標點符號及其他符號。
-
元字符:除普通字符之外的字符。
-
-
應用范圍:被多種工具(如 vim、grep、less 等)和編程語言(如 Perl、Python、C 等)所使用。
-
正則表達式分類:
- 普通正則表達式
- 擴展正則表示,支持更多的元字符。
環境準備
[lth@controller ~ 18:31:13]$ vim words
cat
category
acat
concatenate
dog
字符集
[…]
匹配 [...]
中的任意一個字符。
[lth@controller ~ 18:32:14]$ echo cbt >> words
[lth@controller ~ 18:32:20]$ echo c1t >> words
[lth@controller ~ 18:32:24]$ cat words | grep 'c[ab]t'
cat
category
acat
concatenate
cbt
[a-z] [A-Z] [0-9]
這三個是正則表達式中常用的字符類(字符范圍匹配),用于匹配指定范圍內的單個字符:
-
[a-z]
,匹配所有小寫字母。 -
[A-Z]
,匹配所有大寫字母。 -
[0-9]
,匹配所有數字。 -
它們常結合量詞使用,如
[0-9]+
可匹配一個或多個連續數字。-
[0-9]+
是正則表達式中常用的組合模式,由兩部分構成:[0-9]
:表示匹配任意單個數字(0-9 中的一個)+
:元字符,作為量詞,表示 “匹配前面的元素一次或多次”
結合起來,
[0-9]+
的含義是:匹配一個或多個連續的數字。
-
[lth@controller ~ 18:33:00]$ cat words | grep 'c[a-z]t'
cat
category
acat
concatenate
cbt[lth@controller ~ 18:33:06]$ echo cCt >> words
[lth@controller ~ 18:33:10]$ cat words | grep 'c[A-Z]t'
cCt[lth@controller ~ 18:33:13]$ cat words | grep 'c[0-9]t'
c1t[lth@controller ~ 18:33:17]$ cat words | grep 'c[a-z0-9]t'
cat
category
acat
concatenate
cbt
c1t[lth@controller ~ 18:33:21]$ cat words | grep 'c[a-zA-Z0-9]t'
cat
category
acat
concatenate
cbt
c1t
cCt# 要想匹配-符號,將改符號寫在第一個位置
[lth@controller ~ 18:33:26]$ echo c-t >> words
[lth@controller ~ 18:33:30]$ cat words | grep 'c[-a-zA-Z0-9]t'
cat
category
acat
concatenate
cbt
c1t
cCt
c-t
[^…]
否定字符類,匹配除 [...]
中包含的所有字符以外的任意單個字符。
- 例:
c[^ab]t
匹配 “c” 開頭、“t” 結尾,且中間不是 “a” 或 “b” 的字符串(如匹配 “c1t”) - 注意:
^
僅在字符類開頭時表示否定,若在中間則視為普通字符(如c[a^b]t
會匹配 “cat” 或 “cbt” 等)
[lth@controller ~ 18:45:01]$ cat words | grep 'c[^ab]t'
c1t# ^放中間會被當做普通字符
[lth@controller ~ 18:45:08]$ cat words | grep 'c[a^b]t'
cat
category
acat
concatenate
cbt
.
匹配除換行符(\n
、\r
)之外的任意單個字符,相等于\[^\n\r]
。
- 例:
c.t
可匹配 “cat”、“cbt”、“c1t”、“c-t” 等(只要中間是單個非換行字符)
[lth@controller ~ 18:45:35]$ cat words | grep 'c.t'
cat
category
acat
concatenate
cbt
c1t
cCt
c-t
\
將下一個字符標記為或特殊字符、或原義字符、或向后引用、或八進制轉義符。
-
例, ‘n’ 匹配字符 ‘n’。
\n
匹配換行符。序列\\
匹配\
,而\(
則匹配(
。 -
例:
c\.t
專門匹配 “c.t”(將.
轉義為普通點號) -
注意:對普通字符(如
a
)加\
雖可能匹配,但不建議這樣使用
[lth@controller ~ 18:45:55]$ echo c.t >> words
[lth@controller ~ 18:46:10]$ cat words | grep 'c\.t'
c.t# 匹配普通字符,雖然可以匹配,但強烈建議不要在前面加\
[lth@controller ~ 18:46:14]$ cat words | grep 'c\at'
cat
category
acat
concatenate
|
|
符號是擴展正則中的 “或” 操作符,用于匹配兩項中的任意一項。要匹配 |
,請使用 \|
。
- 需配合
egrep
或grep -E
使用 - 例:
cat|dog
可同時匹配包含 “cat” 或 “dog” 的字符串
# 使用egrep或者grep -E 匹配
[lth@controller ~ 18:48:36]$ cat words | egrep 'cat|dog'
cat
category
acat
concatenate
dog
# 或者
[lth@controller ~ 18:48:41]$ cat words | grep -E 'cat|dog'
cat
category
acat
concatenate
dog
非打印字符
在正則表達式中,非打印字符指的是那些不在屏幕上直接顯示的字符(如換行符、制表符等)。它們在文本處理中非常重要,常需要通過特殊轉義序列來匹配。以下是常見的非打印字符及其正則表示:
字符 | 描述 |
---|---|
\cx | 匹配由x指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個原義的 ‘c’ 字符。 |
\f | 匹配一個換頁符。等價于 \x0c 和 \cL 。 |
\n | 匹配一個換行符。等價于 \x0a 和 \cJ 。 |
\r | 匹配一個回車符。等價于 \x0d 和 \cM 。 |
\s | 匹配任何空白字符,包括空格、制表符、換頁符等等。等價于 [ \f\n\r\t\v] 。注意 Unicode 正則表達式會匹配全角空格符。 |
\S | 匹配任何非空白字符。等價于 [^ \f\n\r\t\v] 。 |
\w | 匹配字母、數字、下劃線。等價于 [A-Za-z0-9_] |
\W | 匹配任何非單詞字符。等價于[^A-Za-z0-9_] |
\t | 匹配一個制表符。等價于 \x09 和 \cI 。 |
\v | 匹配一個垂直制表符。等價于 \x0b 和 \cK 。 |
grep 命令支持
\w
、\W
、\s
、\S
。
定位符
^
匹配行首位置。
[lth@controller ~ 18:51:15]$ cat words | grep '^cat'
cat
category
$
匹配行末位置。
-
作用:限定匹配內容必須出現在行的結尾
-
示例 1:
# 查找以 "cat" 結尾的行,匹配到 "cat"(整行都是 cat)和 "acat"(行尾是 cat) [lth@controller ~ 18:54:57]$ cat words | grep 'cat$' cat acat
-
示例 2:
# `^`匹配行首,`$`匹配行尾,組合起來只匹配整行內容恰好是 "cat"的行。 [lth@controller ~ 18:55:10]$ cat words | grep '^cat$' cat
\b
匹配一個單詞邊界。
-
作用:匹配單詞與非單詞字符之間的位置(如字母與空格、標點、行首 / 行尾的交界處)
-
示例 1:
# `\bcat`匹配以 "cat" 開頭的單詞,包括: # - 單獨的 "cat"(行首單詞) # - "category"(以 cat 開頭的長單詞) # - "hello cat"(空格后的 cat 單詞) [lth@controller ~ 18:58:09]$ cat words | grep '\bcat' cat category hello cat
-
示例 2:
# `cat\b`匹配以 "cat" 結尾的單詞,包括: # - 單獨的 "cat"(行尾單詞) # - "acat"(以 cat 結尾的單詞) # - "hello cat"(空格后的 cat 單詞) [lth@controller ~ 18:58:11]$ cat words | grep 'cat\b' cat acat hello cat
-
示例 3:
# `\bcat\b`只匹配獨立的 "cat" 單詞(前后都是單詞邊界),不匹配包含 cat 的長單詞(如 category、acat) [lth@controller ~ 18:58:19]$ cat words | grep '\bcat\b' cat hello cat
\B
非單詞邊界匹配。
-
作用:匹配不在單詞邊界的位置(即字符之間是連續的單詞字符,如字母與字母之間)
-
示例:
# '\Bcat'匹配 "cat" 前面不是單詞邊界的情況,即 "cat" 前面是其他字母: # - "acat" 中 "cat" 前面是 "a"(非邊界) # - "concatenate" 中包含 "cat" 且前面是其他字母 [lth@controller ~ 19:03:48]$ cat words | grep '\Bcat' acat concatenate
\< 和 \>
-
作用:
\<
匹配單詞左邊界(等同于\b
),\>
匹配單詞右邊界(等同于\b
),是部分工具(如 grep)支持的擴展表示 -
示例 1:
# `\<cat`與`\bcat`效果相同,匹配以 "cat" 開頭的單詞 [lth@controller ~ 19:05:57]$ cat words | grep '\<cat' cat category hello cat
-
示例 2:
# `cat\>`與`cat\b`效果相同,匹配以 "cat" 結尾的單詞 [lth@controller ~ 19:06:41]$ cat words | grep 'cat\>' cat acat hello cat
限定次數
*
匹配前面的子表達式任意次數。
-
作用:允許前面的元素出現 0 次、1 次或多次
-
示例:
# do*g 中 o* 表示 "o 可以出現任意次",所以包含 0 個 o(dg)、1 個 o(dog)、2 個 o(doog)的字符串都能匹配。 [lth@controller ~ 19:09:39]$ echo dg >> words [lth@controller ~ 19:09:42]$ echo doog >> words [lth@controller ~ 19:09:47]$ cat words | grep 'do*g' dog # 匹配:d + o(1次) + g dg # 匹配:d + o(0次) + g doog # 匹配:d + o(2次) + g
+
+
是擴展表達式元字符,匹配前面的子表達式一次以上次數。(擴展表達式,需用egrep
或grep -E
)
-
作用:要求前面的元素至少出現 1 次
-
示例:
# do+g 中 o+ 表示 "o 至少出現 1 次",所以排除了不含 o 的dg。 [lth@controller ~ 19:11:40]$ cat words | egrep 'do+g' dog # 匹配:o出現1次 doog # 匹配:o出現2次
?
?
是擴展表達式元字符,匹配前面的子表達式一次以下次數。
-
作用:允許前面的元素最多出現 1 次
-
示例:
# do?g 中 o? 表示 "o 最多出現 1 次",所以排除了 o 出現 2 次的doog。 [lth@controller ~ 19:11:57]$ cat words | egrep 'do?g' dog # 匹配:o出現1次 dg # 匹配:o出現0次
{n}
{}
是擴展表達式元字符,用于匹配特定次數。例如:{n}
,配置n次。
-
作用:精確指定前面元素的出現次數
-
示例:
# do{2}g 表示 "o 必須出現且僅出現 2 次",所以只匹配doog。 [lth@controller ~ 19:12:40]$ cat words | egrep 'do{2}g' doog # 匹配:o恰好出現2次
{m,n}
{m,n}
,是擴展表達式元字符,用于匹配次數介于m-n之間。
-
作用:限定前面元素出現次數的范圍(包含 m 和 n)
-
示例:
# do{2,3}g 表示 "o 出現 2 次或 3 次",所以排除了 o 出現 4 次的doooog。 [lth@controller ~ 19:14:29]$ echo dooog >> words # o出現3次 [lth@controller ~ 19:14:31]$ echo doooog >> words # o出現4次 [lth@controller ~ 19:14:35]$ cat words | egrep 'do{2,3}g' doog # o出現2次(在2-3范圍內) dooog # o出現3次(在2-3范圍內)
{m,}
{m,}
,是擴展表達式元字符,匹配前面的子表達式m次以上次數。
-
作用:前面的元素出現次數不小于 m
-
示例:
# do{2,}g 表示 "o 至少出現 2 次",所以包含 2 次、3 次、4 次 o 的字符串都匹配。 [lth@controller ~ 19:17:34]$ cat words | egrep 'do{2,}g' doog # o出現2次 dooog # o出現3次 doooog # o出現4次
{,n}
{,n}
,是擴展表達式元字符,匹配前面的子表達式n次以下次數。
-
作用:前面的元素出現次數不大于 n
-
示例:
# do{,3}g 表示 "o 最多出現 3 次",所以排除了 o 出現 4 次的doooog。 [lth@controller ~ 19:18:17]$ cat words | egrep 'do{,3}g' dog # o出現1次 doog # o出現2次 dg # o出現0次 dooog # o出現3次
()
標記一個子表達式。
-
作用:將多個字符視為一個整體,配合限定符使用
-
示例:
[lth@controller ~ 19:19:33]$ echo dogdog >> words # "dog"出現2次 [lth@controller ~ 19:19:35]$ echo dogdogdog >> words # "dog"出現3次 [lth@controller ~ 19:19:41]$ echo dogdogdogdog >> words # "dog"出現4次# 匹配"dog"出現2-3次的字符串 # (dog){2,3} 中,(dog) 將 "dog" 視為一個整體,{2,3} 限定這個整體出現 2-3 次,因此匹配包含 2 個或 3 個連續 "dog" 的字符串。 [lth@controller ~ 19:19:47]$ cat words | egrep '(dog){2,3}' dogdog dogdogdog dogdogdogdog # 包含"dog"3次的部分(前3個"dog")# 匹配"dog"出現至少2次的字符串 [lth@controller ~ 19:19:56]$ cat words | egrep '(dog){2,}' dogdog dogdogdog dogdogdogdog
這些限定符用于精確控制字符或子表達式的出現次數,是正則表達式中實現靈活匹配的核心功能,其中+
、?
、{}
、()
屬于擴展正則,需用egrep
或grep -E
才能生效。
反向引用
反向引用是正則表達式中通過圓括號()
捕獲子匹配(存儲到臨時緩沖區),再用\N
(N
為 1-99 的數字,代表緩沖區編號)引用已捕獲內容的機制。捕獲的子匹配按從左到右順序存儲,\N
用于重復調用對應緩沖區的內容,實現對重復模式的匹配。
示例 1:引用首個捕獲組
[lth@controller ~ 19:28:13]$ echo 'laoma laoniu laohu laoma laoniu laohu' | \
> egrep -o '(laoma) (laoniu).*\1'
# 過濾結果如下
laoma laoniu laohu laoma
- 解析:
(laoma)
是第 1 個捕獲組,匹配字符串laoma
并存儲到緩沖區 1;(laoniu)
是第 2 個捕獲組,匹配laoniu
;.*
匹配任意字符(除換行符);\1
引用第 1 個捕獲組的內容(即laoma
);- 整體匹配 “
laoma laoniu
+ 任意字符 + 再次出現laoma
” 的部分,最終提取出符合該模式的字符串。
示例 2:匹配連續重復的單詞
[lth@controller ~ 19:28:29]$ echo 'Is is the cost of of gasoline going up up?' | \
> egrep -o '\b([a-z]+) \1\b'
# 過濾結果如下
of of
up up
- 解析:
\b
是單詞邊界,確保匹配完整單詞;([a-z]+)
是第 1 個捕獲組,匹配小寫字母組成的單詞;\1
引用該單詞,因此([a-z]+) \1
表示 “一個單詞 + 空格 + 相同單詞”;- 整體匹配連續重復的單詞(如
of of
、up up
)。
示例 3:匹配重復 2 次及以上的單詞
[root@controller ~ 19:30:27]# echo 'Is is the cost of of of gasoline going up up?' | egrep -o '(\b[a-z]+\b\s+)\1{1,}'
# 過濾結果如下
of of of
- 解析:
(\b[a-z]+\b\s+)
是第 1 個捕獲組,匹配 “一個單詞 + 空格”(\s+
表示至少一個空格);\1{1,}
表示引用該捕獲組內容 1 次及以上,即 “(單詞 + 空格) 重復 1 次以上”;- 整體匹配同一單詞連續出現 2 次及以上的情況(如
of of of
是 “of + 空格” 重復 2 次)。
示例 4:匹配重復但中間空格不固定的單詞
[root@controller ~ 19:30:49]# echo 'Is is the cost of of of gasoline going up up?' | egrep -o '(\b[a-z]+\b\s+)\1{1,}'
# 過濾結果如下
of of
- 解析:
- 與示例 3 邏輯相同,但原字符串中
of of
(兩個空格)和of of
(一個空格)分別被捕獲; - 由于捕獲組中
\s+
允許任意多個空格,因此of of
(“of + 兩個空格” 重復 1 次)符合模式,被提取為of of
(輸出時保留原始空格)。
- 與示例 3 邏輯相同,但原字符串中