当前位置: 首页 > news >正文

【Linux】通俗易懂讲解-正则表达式

在这里插入图片描述

  • 博主简介:努力学习的22级计算机科学与技术本科生一枚🌸
  • 博主主页: @Yaoyao2024
  • 往期回顾:【科研小白系列】这些基础linux命令,你都掌握了嘛?
  • 每日一言🌼: 永远不要只看见前方路途遥远 而忘了从前的自己坚持了多久才走到这里。🌺

在这里插入图片描述

核心概念一句话:

正则表达式(Regular Expression,简称 regex)就像文本的“超级搜索/匹配密码”。它用一组特殊符号和规则,描述你想要的文本“模式”,帮你快速查找、提取或修改复杂的字符串。

一、为什么需要正则?

  • 场景1: 在1000行的日志文件里,找出所有包含 errorERRORError 的行(大小写不敏感)。
  • 场景2: 从一堆文件名中,筛选出所有以 .jpg.png 结尾的图片文件。
  • 场景3: 把文件里所有手机号码 138xxxx1234 替换成 [隐私保护]
  • 场景4: 验证用户输入的邮箱地址 xxx@yyy.com 格式是否正确。

没有正则: 你可能需要写很复杂的循环和判断,或者肉眼一条条找,效率极低且易错。
有了正则: 一行命令或表达式就能搞定!这就是它的魔力。就像一个筛黄豆的筛子,只有符合预先设定“孔”的大小的黄豆才能通过!把“黄豆”直接放到筛子里就可以得到想要大小的黄豆。

二、正则表达式基础:认识“通配符”的升级版

Linux中你用过 * (匹配任意字符) 吗?

正则就是更强大、更精确的“通配符”系统。它分为两类:

  1. 基本正则表达式 (BRE): 语法较老,某些元字符需要转义才能发挥特殊作用。常用工具如 grep, sed (默认模式), vi/vim
  2. 扩展正则表达式 (ERE): 语法更现代直观,元字符功能默认开启。常用工具如 grep -E / egrep, sed -E, awk

小白建议: 先重点学习扩展正则表达式 (ERE),它更常用、更易读! 本文主要讲解 ERE。

三、核心元件:构建你的“匹配密码”

想象你在用乐高积木搭一个“文本模具”,只有符合这个模具形状的文本才能被匹配。

1. 普通字符

  • 是什么: 字母 (a-z, A-Z)、数字 (0-9)、大部分标点符号。
  • 作用: 精确匹配它们自己。
  • 例子: cat 匹配字符串 "cat"

2. 元字符 - 超级英雄 (特殊含义符号)

这些是正则的核心力量!必须记住:

  • . (点号):

    • 作用: 匹配任意一个字符(除了换行符 \n)。
    • 例子: c.t 匹配 "cat", "cot", "c@t", "c t" 等。
    • 类比: 扑克牌里的“百搭牌”。
  • * (星号):

    • 作用: 匹配前面的字符或子表达式 0次 或 多次
    • 例子:
      • ab*c:匹配 "ac" (b出现0次), "abc" (b出现1次), "abbc" (b出现2次), "abbbbc" (b出现多次)。
      • .*超级常用! 匹配 任意长度(包括0长度)的任意字符序列(除了换行符)。相当于“什么都行,或者什么都没有”。
    • 类比: “前面的东西可以重复出现很多次,或者干脆不出现”。
  • + (加号):

    • 作用: 匹配前面的字符或子表达式 1次 或 多次。 (比 * 严格一点,至少出现1次)
    • 例子: ab+c 匹配 "abc", "abbc", "abbbbc",但不匹配 "ac" (因为b至少要有1个)。
    • 类比: “前面的东西必须至少出现一次,可以出现很多次”。

这个*+总是成对出现(至少在我学过的离散数学和编译原理中),在编译原理这门课里面,我记得这两个符号表达的含义分别是“星推导”和“加推导”,作用和含义和上面解释的含义是一致的。

  • ? (问号):

    • 作用:
      1. 匹配前面的字符或子表达式 0次 或 1次。(表示可选)
      2. 在限定符 (*, +, ?, {}) 后面使它们变成 非贪婪匹配 (稍后详解)。
    • 例子(作用1): colou?r 匹配 "color" (u出现0次) 和 "colour" (u出现1次)。
    • 类比: “前面的东西可有可无,最多出现一次”。
  • [] (方括号 - 字符组):

    • 作用: 匹配方括号内列出的任意一个字符。
    • 例子:
      • [aeiou]:匹配任意一个小写元音字母 (a, e, i, o, u)。
      • [0-9]:匹配任意一个数字 (等价于 \d,但 \d 不一定在所有工具中都支持,[0-9] 更通用)。
      • [a-zA-Z]:匹配任意一个字母(大小写)。
      • [^abc]^在开头表示否定!匹配除了 a, b, c 之外的任意一个字符。
    • 重要:[] 内,大部分元字符 (如 ., *, +) 会失去特殊含义,只代表它们自己。但 - (定义范围如a-z), ^ (开头表示否定), ] (结束符) 和 \ (转义符) 在 [] 内仍有特殊含义。
    • 类比: “从这个小菜单里选一个字符”。
  • | (竖线 - 或):

    • 作用: 匹配 | 左边右边的表达式。
    • 例子: cat|dog 匹配字符串 "cat" "dog"(gray|grey) 匹配 "gray""grey" (通常和括号 () 一起用)。
    • 类比: “这个或者那个,二选一”。
  • () (圆括号 - 分组):

    • 作用:
      1. 分组: 将多个字符组合成一个子表达式,以便应用限定符 (*, +, ?, {}) 或 |
      2. 捕获: 匹配的内容会被“记住”,可以在替换操作 (sed, 编程语言中) 或模式后向引用 (\1, \2等) 中使用。
    • 例子:
      • (abc)+:匹配 "abc", "abcabc", "abcabcabc" 等。
      • (ab|cd)ef:匹配 "abef""cdef"
    • 类比: “把这几块积木粘在一起当成一个整体来处理,并且记住这个整体长什么样”。
  • {} (花括号 - 量词/重复次数):

    • 作用: 精确指定前面字符或子表达式出现的次数。
    • 格式:
      • {n}:精确匹配 n 次。
      • {n,}:匹配至少 n 次。
      • {n,m}:匹配至少 n 次,至多 m 次。
    • 例子:
      • a{3}:匹配 "aaa"
      • a{2,4}:匹配 "aa", "aaa", "aaaa"
      • [0-9]{4}:匹配任意连续的4位数字(如年份、部分电话号码)。
    • 类比: “前面的东西必须精确出现/最少出现/最多出现多少次”。
  • ^ (脱字符) 和 $ (美元符):

    • 作用: 匹配位置,而不是具体字符。
      • ^:匹配一行的开头
      • $:匹配一行的结尾
    • 例子:
      • ^Hello:匹配所有以 "Hello" 开头的行。
      • world$:匹配所有以 "world" 结尾的行。
      • ^$:匹配空行 (开头紧跟着结尾)。
      • ^[A-Z]:匹配所有以大写字母开头的行。
    • 类比: ^ 是“行首的锚点”, $ 是“行尾的锚点”。用来把匹配“钉”在行的特定位置。
  • \ (反斜杠 - 转义符):

    • 作用:
      1. 开启元字符的特殊含义: 在 BRE 中,要使 {, }, (, ), +, ?, | 具有特殊含义,有时需要在它们前面加 \ (在 ERE 中通常不需要)。
      2. 关闭元字符的特殊含义: 如果一个元字符 (如 ., *, ?) 你想让它表示普通字符本身(比如你想匹配一个实际的点号.),就在它前面加 \
      3. 引入特殊序列: 后面介绍。
    • 例子:
      • my\.domain\.com:匹配 "my.domain.com" (这里的 . 就是普通的点号)。
      • \*:匹配一个实际的星号字符 *
      • \\:匹配一个实际的反斜杠字符 \
    • 类比: “魔法开关”。给普通字符加魔法,或者去掉元字符的魔法让它变普通。

3. 预定义字符类 (便捷写法)

这些是常用字符组的缩写:

  • \d 匹配一个数字字符。等价于 [0-9](注意:在基本正则 grep/sed 中可能不支持,用 [0-9] 更安全)
  • \D 匹配一个非数字字符。等价于 [^0-9]
  • \w 匹配一个单词字符 (字母、数字、下划线 _)。等价于 [a-zA-Z0-9_](注意同上)
  • \W 匹配一个非单词字符。等价于 [^a-zA-Z0-9_]
  • \s 匹配一个空白字符 (空格、制表符 \t、换行符 \n、回车符 \r 等)。(注意同上)
  • \S 匹配一个非空白字符
  • \b 匹配一个单词边界(单词的开头或结尾,即 \w\W 之间的位置)。例如 \bcat\b 匹配独立的单词 "cat",不会匹配 "catalog""scatter" 中的 "cat"

小白提示: 在 Linux 命令行工具 (grep, sed, awk) 中,\d, \w, \s不一定默认支持 (尤其在 BRE 模式)。[0-9], [a-zA-Z], [[:space:]] 是更可靠的选择。在编程语言 (Python, Perl, JavaScript) 中通常支持良好。

4. 贪婪匹配 vs. 非贪婪匹配 (重要概念!)

  • 贪婪匹配 (Greedy): 默认行为!限定符 (*, +, ?, {}) 会尽可能多地匹配字符。
  • 非贪婪匹配 (Lazy/Reluctant): 在限定符后面加上 ?,使其尽可能少地匹配字符。

例子解析:
假设文本是: "<em>重要内容</em> 和 <em>其他内容</em>"

  • 贪婪模式: /<em>.*<\/em>/
    • 匹配结果: "<em>重要内容</em> 和 <em>其他内容</em>" (整个字符串,从第一个 <em> 到最后一个 </em>,因为它“贪婪”地吃掉了中间的所有字符,包括第二个 <em></em>)
  • 非贪婪模式: /<em>.*?<\/em>/
    • 匹配结果: "<em>重要内容</em>" (只匹配到第一个 </em> 就停止了,因为它“不贪心”)
    • 如果需要匹配所有,通常配合全局匹配标志使用(在工具或编程语言中)。

在 Linux 工具中: sedawk 默认贪婪。grep -P (Perl 正则,支持非贪婪 *?) 或 sed 结合其他技巧可以实现非贪婪,但在基础命令行中有时需要更精确地写表达式来避免贪婪问题。.*?grep -Pperl/python 脚本中有效。

四、在 Linux 命令行中使用正则 (实战!)

最常用的三个工具:grep, sed, awk。这里重点看 grepsed 的基础正则应用。

1. grep - 文本搜索利器

  • 作用: 在文件或输入中搜索包含匹配正则模式的行。
  • 常用选项:
    • -i:忽略大小写。
    • -v:反向匹配,显示不包含模式的行。
    • -E:使用扩展正则表达式 (ERE) (推荐!)。
    • -P:使用 Perl 正则 (功能最强,支持非贪婪 *? 等,但非所有系统默认支持)。
    • -o:只输出匹配到的部分 (而不是整行)。
    • -n:显示匹配行的行号。
    • -r / -R:递归搜索目录下的文件。
  • 例子:
    # 在 file.txt 中查找包含 "error" (忽略大小写) 的行
    grep -i 'error' file.txt# 使用 ERE 查找包含 "error" 或 "warning" 的行
    grep -E 'error|warning' file.txt# 查找以数字开头、以句点结束的行
    grep -E '^[0-9].*\.$' file.txt# 查找所有格式为 xxx-xxx-xxxx 的电话号码 (简单示例)
    grep -E '[0-9]{3}-[0-9]{3}-[0-9]{4}' contacts.txt# 查找包含 "functionName(" 的行 (匹配函数调用)
    grep 'functionName\(' code.js  # 注意转义 ( (BRE 可能需要)# 递归搜索当前目录及子目录的 .py 文件,查找 'import os' 行
    grep -r --include='*.py' 'import os' .
    

2. sed - 流编辑器,文本替换大师

  • 作用: 读取输入流,按行处理(查找、替换、删除、插入等),输出结果。非常适合基于正则的文本替换!
  • 常用选项:
    • -E:使用扩展正则表达式 (ERE) (推荐!)。
    • -i原地编辑文件 (小心使用!建议先不加 -i 测试)。-i.bak 先备份原文件。
  • 核心命令: s/pattern/replacement/flags
    • s:表示替换 (substitute)。
    • pattern:要查找的正则表达式。
    • replacement:替换成的文本。
    • flags:标志位,常用:
      • g:全局替换 (一行中的所有匹配),不加则只替换每行第一个匹配。
      • p:打印替换后的行 (通常与 -n 选项一起用)。
  • 例子:
    # 将 file.txt 中所有的 "colour" 替换成 "color" (标准输出,不修改文件)
    sed 's/colour/color/g' file.txt# 使用 ERE 将每行第一个数字替换成 "NUMBER" (原地编辑,先备份)
    sed -i.bak -E 's/[0-9]+/NUMBER/' data.txt# 删除所有空白行 (标准输出)
    sed '/^$/d' file.txt  # /pattern/d 命令删除匹配行# 将手机号 138xxxx5678 替换成 [隐私保护] (简单示例)
    sed -E 's/1[3-9][0-9]{9}/[隐私保护]/g' users.txt# 在包含 "START" 的行后面插入一行 "--BEGIN DATA--" (标准输出)
    sed '/START/a --BEGIN DATA--' file.txt
    

awk 也是一个强大的文本处理工具,内置对正则的支持非常好,功能远超 grepsed (可以编程),但学习曲线更陡峭。建议掌握 grepsed 基础后再学 awk

五、用例积累

主要用于积累博主平时用到的一些正则例子

  1. 去掉文件后缀,获得文件名,将其文件名作为一个list输入的指定文件
# 提取 /data1/share/te5/af3_json 中的 pdb-id(去掉 .json 后缀)
ls /data1/share/te5/af3_json| sed 's/\.json$//' |sort > list.txt
  • 但当通过管道(|)输出到其他命令时,ls 会自动切换为 “每行一个文件名” 的格式(sed是按行处理)。
  • sed 's/\.json$//' 用于移除文件名末尾的 .json。
http://www.dtcms.com/a/324572.html

相关文章:

  • 从Redisson源码角度深入理解Redis分布式锁的正确实现
  • JetPack系列教程(三):Lifecycle——给Activity和Fragment装个“生命探测仪“
  • redis主从模型与对象模型
  • Beelzebub靶机练习
  • 代码随想录算法训练营第五十九天|图论part9
  • 下一代防火墙总结
  • 【软考中级网络工程师】知识点之 PPP 协议:网络通信的基石
  • Stlink识别不到-安装驱动
  • Hutool-RedisDS:简化Redis操作的Java工具类
  • 【Python 小脚本·大用途 · 第 1 篇】
  • 在VMware中安装统信UOS桌面专业版
  • Python 的浅拷贝 vs 深拷贝(含嵌套可变对象示例与踩坑场景)
  • 基础算法(11)——栈
  • 【3D图像技术分析与实现】CityGaussianV2 工作解析
  • log4cpp、log4cplus 与 log4cxx 三大 C++ 日志框架
  • 机器学习数学基础:46.Mann-Kendall 序贯检验(Sequential MK Test)
  • Java集合框架、Collection体系的单列集合
  • 有限元方法中的数值技术:追赶法求解三对角方程
  • 【鸿蒙/OpenHarmony/NDK】什么是NDK? 为啥要用NDK?
  • PCB知识07 地层与电源层
  • LLIC:基于自适应权重大感受野图像变换编码的学习图像压缩
  • 每日一题:使用栈实现逆波兰表达式求值
  • Redis高级
  • AAAI 2025丨具身智能+多模态感知如何精准锁定目标
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘ray’问题
  • Python数据分析常规步骤整理
  • Mysql系列--5、表的基本查询(下)
  • Speaking T2 - Dining Hall to CloseDuring Spring Break
  • 机器学习 DBScan
  • 一键复制产品信息到剪贴板