【运维进阶】Linux 正则表达式

Linux 正则表达式

  1. 定义:正则表达式是一种pattern(模式),用于与待搜索字符串匹配,以查找一个或多个目标字符串。

  2. 组成:自成体系,由两类字符构成

    • 普通字符:未被显式指定为元字符的所有可打印和不可打印字符,包括大小写字母、数字、标点符号及其他符号。

    • 元字符:除普通字符之外的字符。

  3. 应用范围:被多种工具(如 vim、grep、less 等)和编程语言(如 Perl、Python、C 等)所使用。

  4. 正则表达式分类:

    • 普通正则表达式
    • 扩展正则表示,支持更多的元字符。

环境准备

bash 复制代码
[lth@controller ~ 18:31:13]$ vim words
cat
category
acat
concatenate
dog

字符集

[...]

匹配 [...] 中的任意一个字符。

bash 复制代码
[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]+ 的含义是:匹配一个或多个连续的数字

bash 复制代码
[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" 等)
bash 复制代码
[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" 等(只要中间是单个非换行字符)
bash 复制代码
[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)加 \ 虽可能匹配,但不建议这样使用

bash 复制代码
[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
|

| 符号是扩展正则中的 "或" 操作符,用于匹配两项中的任意一项。要匹配 |,请使用 \|

  • 需配合 egrepgrep -E 使用
  • 例:cat|dog 可同时匹配包含 "cat" 或 "dog" 的字符串
bash 复制代码
# 使用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

定位符

^

匹配行首位置。

bash 复制代码
[lth@controller ~ 18:51:15]$ cat words | grep '^cat'
cat
category
$

匹配行末位置。

  • 作用:限定匹配内容必须出现在行的结尾

  • 示例 1:

    bash 复制代码
    # 查找以 "cat" 结尾的行,匹配到 "cat"(整行都是 cat)和 "acat"(行尾是 cat)
    [lth@controller ~ 18:54:57]$ cat words | grep 'cat$'
    cat
    acat
  • 示例 2:

    bash 复制代码
    # `^`匹配行首,`$`匹配行尾,组合起来只匹配整行内容恰好是 "cat"的行。
    [lth@controller ~ 18:55:10]$ cat words | grep '^cat$'
    cat
\b

匹配一个单词边界。

  • 作用:匹配单词与非单词字符之间的位置(如字母与空格、标点、行首 / 行尾的交界处)

  • 示例 1:

    bash 复制代码
    # `\bcat`匹配以 "cat" 开头的单词,包括:
    # - 单独的 "cat"(行首单词)
    # - "category"(以 cat 开头的长单词)
    # - "hello cat"(空格后的 cat 单词)
    [lth@controller ~ 18:58:09]$ cat words | grep '\bcat'
    cat
    category
    hello cat
  • 示例 2:

    bash 复制代码
    # `cat\b`匹配以 "cat" 结尾的单词,包括:
    # - 单独的 "cat"(行尾单词)
    # - "acat"(以 cat 结尾的单词)
    # - "hello cat"(空格后的 cat 单词)
    [lth@controller ~ 18:58:11]$ cat words | grep 'cat\b'
    cat
    acat
    hello cat
  • 示例 3:

    bash 复制代码
    # `\bcat\b`只匹配独立的 "cat" 单词(前后都是单词边界),不匹配包含 cat 的长单词(如 category、acat)
    [lth@controller ~ 18:58:19]$ cat words | grep '\bcat\b'
    cat
    hello cat
\B

非单词边界匹配。

  • 作用:匹配不在单词边界的位置(即字符之间是连续的单词字符,如字母与字母之间)

  • 示例:

    bash 复制代码
    # '\Bcat'匹配 "cat" 前面不是单词边界的情况,即 "cat" 前面是其他字母:
    # - "acat" 中 "cat" 前面是 "a"(非边界)
    # - "concatenate" 中包含 "cat" 且前面是其他字母
    [lth@controller ~ 19:03:48]$ cat words | grep '\Bcat'
    acat
    concatenate
\< 和 \>
  • 作用:\<匹配单词左边界(等同于\b),\>匹配单词右边界(等同于\b),是部分工具(如 grep)支持的扩展表示

  • 示例 1:

    bash 复制代码
    # `\<cat`与`\bcat`效果相同,匹配以 "cat" 开头的单词
    [lth@controller ~ 19:05:57]$ cat words | grep '\<cat'
    cat
    category
    hello cat
  • 示例 2:

    bash 复制代码
    # `cat\>`与`cat\b`效果相同,匹配以 "cat" 结尾的单词
    [lth@controller ~ 19:06:41]$ cat words | grep 'cat\>'
    cat
    acat
    hello cat

限定次数

*

匹配前面的子表达式任意次数

  • 作用:允许前面的元素出现 0 次、1 次或多次

  • 示例:

    bash 复制代码
    # 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
+

+ 是扩展表达式元字符,匹配前面的子表达式一次以上次数 。(扩展表达式,需用egrepgrep -E

  • 作用:要求前面的元素至少出现 1 次

  • 示例:

    bash 复制代码
    # do+g 中 o+ 表示 "o 至少出现 1 次",所以排除了不含 o 的dg。
    [lth@controller ~ 19:11:40]$ cat words | egrep 'do+g'
    dog    # 匹配:o出现1次
    doog   # 匹配:o出现2次
?

? 是扩展表达式元字符,匹配前面的子表达式一次以下次数

  • 作用:允许前面的元素最多出现 1 次

  • 示例:

    bash 复制代码
    # 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次。

  • 作用:精确指定前面元素的出现次数

  • 示例:

    bash 复制代码
    # 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)

  • 示例:

    bash 复制代码
    # 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

  • 示例:

    bash 复制代码
    # 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

  • 示例:

    bash 复制代码
    # 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次
()

标记一个子表达式。

  • 作用:将多个字符视为一个整体,配合限定符使用

  • 示例:

    bash 复制代码
    [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

这些限定符用于精确控制字符或子表达式的出现次数,是正则表达式中实现灵活匹配的核心功能,其中+?{}()属于扩展正则,需用egrepgrep -E才能生效。

反向引用

反向引用是正则表达式中通过圆括号()捕获子匹配(存储到临时缓冲区),再用\NN为 1-99 的数字,代表缓冲区编号)引用已捕获内容的机制。捕获的子匹配按从左到右顺序存储,\N用于重复调用对应缓冲区的内容,实现对重复模式的匹配。

示例 1:引用首个捕获组

bash 复制代码
[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:匹配连续重复的单词

bash 复制代码
[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 ofup up)。

示例 3:匹配重复 2 次及以上的单词

bash 复制代码
[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:匹配重复但中间空格不固定的单词

bash 复制代码
[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(输出时保留原始空格)。
相关推荐
kunge201333 分钟前
Ubuntu22.04 安装virtualbox7.1
linux·virtualbox
清溪54934 分钟前
DVWA中级
linux
MUY09901 小时前
应用控制技术、内容审计技术、AAA服务器技术
运维·服务器
楠奕1 小时前
elasticsearch8.12.0安装分词
运维·jenkins
Sadsvit1 小时前
源码编译安装LAMP架构并部署WordPress(CentOS 7)
linux·运维·服务器·架构·centos
xiaok1 小时前
为什么 lsof 显示多个 nginx 都在 “使用 443”?
linux
java资料站2 小时前
Jenkins
运维·jenkins
苦学编程的谢2 小时前
Linux
linux·运维·服务器
G_H_S_3_2 小时前
【网络运维】Linux 文本处理利器:sed 命令
linux·运维·网络·操作文本
Linux运维技术栈2 小时前
多系统 Node.js 环境自动化部署脚本:从 Ubuntu 到 CentOS,再到版本自由定制
linux·ubuntu·centos·node.js·自动化