欢迎光临
我们一直在努力

Linux 正则表达式详解(基础 + 扩展 + 实操)

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
    aa

    abd
    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],跨平台更稳定
  • 赞(0)
    未经允许不得转载:171主机测评 » Linux 正则表达式详解(基础 + 扩展 + 实操)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址