正则表达式和三剑客

一、为什么要学正则表达式

  1. 文本处理效率高

    • 在处理大量文本时,比如从网页源代码中提取特定的链接、从日志文件中筛选出符合特定模式的记录等。如果手动逐行处理文本,会非常耗时且容易出错。而正则表达式提供了一种简洁而强大的方式来描述文本模式,能够快速地匹配、查找、替换符合特定模式的文本内容。
    • 例如,你有一个包含成千上万个电子邮件地址的文本文件,需要从中提取出所有以“.com”结尾的电子邮件地址。使用正则表达式可以通过简单的模式“[a - zA - Z0 - 9.]+@[a - zA - Z0 - 9]+.com”来快速完成提取任务,而不是手动逐个检查每个电子邮件地址。
  2. 广泛应用于多种编程语言和工具

    • 正则表达式几乎被所有主流的编程语言(如Python、Java、JavaScript等)所支持。同时,许多文本编辑器(如Notepad++、Sublime Text等)和命令行工具(如grep、sed等)也都支持正则表达式。这意味着学会正则表达式后,可以在不同的环境中使用相同的规则来处理文本,具有很强的通用性。
    • 比如,在Python中可以使用re模块来处理正则表达式,在JavaScript中可以通过RegExp对象来操作。无论你是在开发一个网站,还是在进行数据清洗等后端任务,正则表达式都能发挥作用。
  3. 数据验证和格式化

    • 可以用于验证用户输入的数据是否符合特定的格式。例如,验证电话号码、身份证号码、日期格式等。也可以用于对数据进行格式化,比如将日期格式从“YYYY - MM - DD”转换为“MM/DD/YYYY”。
    • 以验证手机号码为例,在中国,手机号码的正则表达式模式可以是“1[3 - 9]\d{9}”。这样可以快速检查用户输入的是否是一个合法的手机号码。

二、什么是正则表达式

正则表达式是一种用于描述文本模式的工具。它是由普通字符(如字母、数字、标点符号等)和特殊字符(称为元字符)组成的字符序列。

  1. 普通字符
    • 普通字符在正则表达式中表示它们自身。例如,正则表达式“abc”可以匹配文本中的“abc”字符串。如果文本是“abcdef”,那么它会匹配从开头开始的“abc”部分。
  2. 元字符

    • 元字符具有特殊的含义,用于定义更复杂的模式。
    • 例如:
      • “.”(点号)可以匹配除换行符以外的任意单个字符。所以正则表达式“a.c”可以匹配“abc”“a c”“a9c”等。
      • “*”(星号)表示前面的字符可以出现0次或多次。
      • y* 重复y 零次,多次
        
      • “+”(加号)表示前面的字符可以出现1次或多次。例如,“ab+c”可以匹配“abc”“abbbc”,但不能匹配“ac”。
      • “?”(问号)表示前面的字符可以出现0次或1次。例如,“ab?c”可以匹配“ac”和“abc”。
    • 还有用于表示字符集合的元字符,如“[]”。例如,“[abc]”可以匹配“a”“b”或“c”中的任意一个字符。而“[a - z]”可以匹配任意小写字母。
  3. 分组和引用

    • 可以使用“()”来进行分组。分组有多种用途,例如在匹配后进行替换操作时,可以通过引用分组来实现复杂的替换。
    • 例如,正则表达式“(\d{3})(\d{4})”可以匹配类似“1234567”这样的数字串,并且可以通过分组分别获取前面的三位数“123”和后面的四位数“4567”。

三、怎么学正则表达式

  1. 学习基本语法规则
    • 首先要熟悉正则表达式的基本元字符及其含义,如前面提到的“.”“*”“+”“?”“[]”等。可以通过阅读相关的书籍或在线教程来系统地学习这些规则。例如,《正则表达式必知必会》这本书是一本很好的入门书籍,它详细地介绍了正则表达式的基本概念和语法。
    • 同时,要多做一些简单的练习来巩固这些规则。比如,给定一些简单的文本和模式,尝试手动判断是否能够匹配,或者自己编写模式来匹配特定的文本内容。
  2. 使用在线工具进行实践
    • 有许多在线的正则表达式测试工具,如regex101.com。这些工具允许你输入正则表达式和测试文本,然后会显示匹配的结果,并详细解释匹配的过程。
    • 你可以在这些工具上尝试不同的模式,观察它们是如何匹配文本的。例如,当你想匹配一个网页中的所有图片链接(通常是以“.jpg”“png”等结尾),可以在工具中输入相关的正则表达式模式,如“<img src=\"\"+.(jpg|png)\"”,并输入网页源代码作为测试文本,查看匹配的结果是否符合预期。
  3. 结合编程语言学习
    • 选择一种你熟悉的编程语言,如Python。在Python中,使用re模块来学习正则表达式。
    • 例如,以下是一个简单的Python代码片段,用于在一个字符串中查找所有的数字:
      import re
      text = "abc123def456"
      numbers = re.findall("\d+", text)
      print(numbers)
      
    • 通过这样的实践,可以更好地理解正则表达式在实际编程中的应用,并且可以深入学习如何处理匹配结果,如替换、分割等操作。

linux和正则表达式

  1. grep命令与正则表达式
    • 基本用法
      • grep是Linux中最常用的文本搜索工具,它支持基本的正则表达式。例如,如果你有一个文本文件example.txt,内容是一些水果名称“apple”“banana”“cherry”“date”,想要查找包含字母“a”开头的单词,可以使用命令grep "^a" example.txt。这里的^是正则表达式中的元字符,表示行的开头,所以^a表示以“a”开头的行。
    • 扩展正则表达式选项
      • 对于更复杂的正则表达式,可以使用-E选项来启用扩展正则表达式。例如,要查找文件中以“a”开头或者以“c”结尾的单词,可以使用grep -E "^a|c$" example.txt。其中|表示“或”的关系,$表示行的结尾。
  2. sed命令与正则表达式
    • 基本替换功能
      • sed主要用于对文本进行编辑,它可以基于正则表达式进行替换操作。例如,有一个文件test.txt,内容是“Hello, world! How are you?”,想要将所有的“world”替换为“Linux”,可以使用命令sed 's/world/Linux/g' test.txt。这里s表示替换操作,/用于分隔模式和替换内容,g表示全局替换(即一行中有多个匹配也全部替换)。
    • 基于正则表达式的行选择
      • sed还可以根据正则表达式选择特定的行进行操作。例如,要删除文件中所有以“#”开头的注释行,可以使用sed '/^#/d' file.txt。其中/^#/是正则表达式,用于匹配以“#”开头的行,d表示删除操作。
  3. awk命令与正则表达式
    • 基于模式的文本处理
      • awk是一种强大的文本处理工具,它也支持正则表达式。例如,有一个包含学生成绩的文件grades.txt,格式为“姓名 成绩”,如“Tom 80”“Jerry 90”。想要打印出成绩大于85分的学生姓名,可以使用命令awk '$2>85 {print $1}' grades.txt。这里$2表示第二列(成绩列),$1表示第一列(姓名列)。如果要使用正则表达式匹配姓名列,可以在模式部分添加正则表达式。例如,要打印出姓名以“J”开头的学生成绩,可以使用awk '$1~/^J/ {print $2}' grades.txt。这里~表示匹配操作,$1~/^J/表示第一列(姓名列)匹配以“J”开头的正则表达式。
  4. 在vi/vim编辑器中使用正则表达式
    • 查找操作
      • vivim编辑器中,可以使用/?来进行正向和反向查找。例如,在编辑一个文本文件时,要查找单词“function”,可以在命令模式下输入/function,然后按回车键。如果要使用正则表达式进行查找,比如查找以“func”开头的单词,可以输入/func\w*。这里\w表示单词字符(字母、数字、下划线),*表示前面的字符可以出现0次或多次。
    • 替换操作
      • vi/vim中进行替换操作时,也可以使用正则表达式。例如,要将文件中所有的“color”替换为“colour”,可以在命令模式下输入:%s/color/colour/g。其中:%s表示在整个文件中进行替换操作,/用于分隔模式和替换内容,g表示全局替换。如果要基于正则表达式进行更复杂的替换,比如将所有以“num”开头的变量名后面添加“_var”,可以输入:%s/num\w*/&_var/g。这里&表示匹配的内容,也就是前面的num\w*部分。

image-20220403163240849

什么是正则表达式

  • 正则表达式就是为了处理大量的字符串而定义的一套规则和方法。

  • 通过定义的这些特殊符号的辅助,系统管理员就可以快速过滤,替换或输出需要的字符串。

  • Linux 正则表达式一般以行为单位处理的。

image-20220405180916410

如何用正则表达式

通常Linux运维工作,都是面临大量带有字符串的内容,如

  • 配置文件
  • 程序代码
  • 命令输出结果
  • 日志文件

且此类字符串内容,我们常会有特定的需要,查找出符合工作需要的特定的字符串,因此正则表达式就出现了

  • 正则表达式是一套规则和方法
  • 正则工作时以单位进行,一次处理一行
  • 正则表达式化繁为简,提高工作效率
  • linux仅受三剑客(sed、awk、grep)支持,其他命令无法使用

运维日常和正则

在运维工作中,正则表达式是一个非常强大的工具,可以用于文本处理、日志分析、配置管理等诸多场景。

一、日志分析

  1. 匹配特定错误信息

    • 例如,在一个Web服务器的日志文件中,你想要找到所有包含“404 Not Found”错误的记录。假设日志文件的每一行记录了一次请求的相关信息,你可以使用正则表达式来匹配包含“404 Not Found”的行。
    • 在Linux系统中,使用grep命令结合正则表达式来查找。正则表达式模式可以是404 Not Found,完整的grep命令如下:
      grep "404 Not Found" access.log
      
    • 如果想要更灵活地匹配,比如“404”和“Not Found”之间可能有其他字符,正则表达式可以写成404.*Not Found。这里的.*表示匹配零个或多个任意字符。
  2. 提取关键信息

    • 以分析Nginx访问日志为例,日志格式可能是$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"
    • 如果你想提取所有的IP地址($remote_addr),可以使用grep和正则表达式。假设IP地址是类似192.168.1.1这样的格式,正则表达式模式可以是[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}。命令如下:
      grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' access.log
      
    • 这里-o选项表示只输出匹配的部分,-E选项表示使用扩展正则表达式。

二、配置管理

  1. 检查配置文件中的参数设置
    • 在服务器的配置文件(如/etc/nginx/nginx.conf)中,你可能需要检查某个特定的参数是否正确设置。例如,检查server_name参数是否设置为预期的值。
    • 假设预期的server_nameexample.com,可以使用grep和正则表达式来查找配置文件中对应的行。正则表达式模式为server_name example.com;,命令如下:
      grep "server_name example.com;" /etc/nginx/nginx.conf
      
    • 如果要检查server_name是否包含某个域名的子域名,可以使用更复杂的正则表达式。比如server_name.*\.example.com;,这个表达式可以匹配像sub.example.com这样的子域名设置。
  2. 替换配置文件中的内容
    • 有时候需要在配置文件中批量修改某些设置。例如,将所有旧的IP地址替换为新的IP地址。
    • 可以使用sed命令结合正则表达式来完成。假设旧IP是192.168.1.1,新IP是10.0.0.1,在配置文件config.ini中进行替换,正则表达式模式为192.168.1.1sed命令如下:
      sed -i's/192.168.1.1/10.0.0.1/g' config.ini
      
    • 这里-i选项表示直接在文件中进行修改,s/旧内容/新内容/gsed的替换命令格式,g表示全局替换。

三、文件和目录操作

  1. 在文件列表中筛选文件
    • 当使用ls命令列出文件时,可以结合grep和正则表达式来筛选出符合特定模式的文件。例如,在一个目录中有很多备份文件,文件名格式是backup_YYYYMMDD.tar.gz,你想找到2025年1月份的备份文件。
    • 正则表达式模式可以是backup_202501[0 - 9]{2}\.tar\.gz,命令如下:
      ls | grep "backup_202501[0 - 9]{2}\.tar\.gz"
      
  2. 验证文件名的合法性
    • 假设在一个文件上传系统中,运维人员需要验证文件名是否符合特定的规则。例如,文件名只能包含字母、数字和下划线,且长度在1到20个字符之间。
    • 正则表达式模式可以是^[a - zA - Z0 - 9_]{1,20}$。这个表达式^表示匹配字符串的开头,[a - zA - Z0 - 9_]{1,20}表示匹配1到20个字母、数字或下划线,$表示匹配字符串的结尾。可以使用脚本语言(如Python)来进行验证:
      import re
      filename = "test_file_123"
      pattern = re.compile('^[a - zA - Z0 - 9_]{1,20}$')
      if pattern.match(filename):
        print("文件名合法")
      else:
        print("文件名不合法")
      

这些只是运维工作中使用正则表达式的一些常见场景,正则表达式的应用非常广泛,熟练掌握它可以大大提高运维工作的效率。

学正则的注意事项

  • 正则表达式应用非常广泛,很多编程语言都支持正则表达式,用于处理字符串提取数据。
  • Linux下普通命令无法使用正则表达式的,只能使用linux下的三个命令,结合正则表达式处理。
    • sed
    • grep
    • awk
  • 通配符是大部分普通命令都支持的,用于查找文件或目录
  • 而正则表达式是通过三剑客命令在文件(数据流)中过滤内容的,注意区别
  • 以及注意字符集,需要设置LC_ALL=C,注意这一点很重要

关于字符集设置

你会发现很多shell脚本里都有这么一个语句如下

image-20220403193453007

作用是修改linux的字符集,通过locale命令可以查看本地字符集设置

linux通过如下变量设置程序运行的不同语言环境,如中文、英文环境。


[root@yuchao-tx-server ~]# locale
LANG=en_US.UTF-8
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=zh_CN.UTF-8

一般我们会使用$LANG变量来设置linux的字符集,一般设置为我们所在的地区,如zh_CN.UTF-8

[root@yuchao-tx-server ~]# echo $LANG
en_US.UTF-8

为了让系统能正确执行shell语句(由于自定义修改的不同语言环境,对一些特殊符号的处理区别,如中文输入法,英文输入法下的标点符号等,导致shell无法执行)

我们会使用如下语句,恢复linux的所有的本地化设置,恢复系统到初始化的语言环境。

[root@yuchao-tx-server ~]# export LC_ALL=C

通配符和正则的区别

1.从语法上就记住,只有awk、gre、sed才识别正则表达式符号、其他都是通配符

2.从用法上区分

  • 表达式操作的是文件、目录名(属于是通配符)
  • 表达式操作的是文件内容(正则表达式)

3.比如如下符号区别

通配符和正则表达式 都有  *  ?  [abcd] 符号
通配符中,都是用来标识任意的字符
如 ls *.log,可以找到a.log  b.log   ccc.log


正则中,都是用来表示这些符号前面的字符,出现的次数,如

grep 'a*'

实际案例

通配符,一般用于对文件名的处理,查找文件
如ls命令结合*
意思是匹配任意字符
[root@yuchao-tx-server test]# ls *.log
1.log  2.log  3.log  4.log  5.log


而三剑客,结合*符号,是处理文件内容,如grep
此时的*作用就不一样了

image-20220403164716418

正则表达式分类

正则表达式主要可以分为以下几类:

  1. 基本正则表达式(BRE)

    • 特点:基本正则表达式是最基础的类型。它的功能相对较为简单,在一些早期的Unix工具(如grep的基本模式)中被广泛使用。它的元字符集比较有限,例如一些特殊字符需要通过转义才能实现特殊功能。
    • 示例:在BRE中,“.”(点)字符匹配除换行符之外的任何单个字符。如果要匹配字符“.”本身,需要使用“.”进行转义。像“a.c”这样的表达式可以匹配“abc”“a c”等,只要中间是一个除换行符外的字符就行。
    • 应用场景:适用于简单的文本匹配任务,在一些对正则表达式功能要求不高,且需要考虑兼容性的旧系统或简单脚本中使用。
  2. 扩展正则表达式(ERE)

    • 特点:扩展正则表达式在基本正则表达式的基础上增加了更多的功能。它支持更多的元字符和操作符,使得模式匹配更加灵活和强大。例如,它允许使用“+”来表示前面的字符或子表达式出现一次或多次,“?”表示前面的字符或子表达式出现零次或一次等。
    • 示例:“a+b”这个ERE表达式可以匹配“ab”“aab”“aaab”等,其中“+”表示前面的“a”字符可以出现一次或多次。而在BRE中没有这种简洁的表示方式,要达到类似效果会更复杂。
    • 应用场景:在需要更复杂的模式匹配,如文本处理工具(如高级的grep -E选项)、文本编辑器的高级查找替换功能等场景下使用,能够更高效地处理复杂的文本模式。
  3. Perl兼容正则表达式(PCRE)

    • 特点:PCRE是一种功能强大的正则表达式类型。它在很大程度上兼容Perl语言中的正则表达式语法,并且综合了基本正则表达式和扩展正则表达式的许多特性,同时还增加了自己独有的功能。例如,它支持反向引用,可以通过“\1”“\2”等形式引用前面匹配的子表达式。
    • 示例:在PCRE中,“(a(b))\1”这个表达式,首先“(a(b))”会匹配“ab”,并且将“ab”作为一个整体,同时内部的“(b)”也会被记住,“\1”会引用整个“ab”部分,所以这个表达式可以匹配“abab”。
    • 应用场景:由于其强大的功能,被广泛应用于各种编程语言中,如PHP、Python(通过re模块,在一定程度上支持PCRE语法)等,用于字符串处理、数据验证(如验证邮箱、URL等格式)、文本提取等众多任务。

使用正则表达式的问题是、有两大类正则表达式规范、linux不同的应用程序,会使用不同的正则表达式。

例如

  • 不同的编程语言使用正则(python,java)
  • Linux实用工具(sed、awk、grep)
  • 其他软件使用正则(mysql、nginx)

正则表达式是通过正则表达式引擎(regular expression engine)实现的。正则表达式引擎是 一套底层软件,负责解释正则表达式模式并使用这些模式进行文本匹配。

在Linux中,有两种流行的正则表达式引擎:

基于unix标准下的正则表达式符号规则有两类:
POSIX基础正则表达式(basic regular expression,BRE)引擎

POSIX扩展正则表达式(extended regular expression,ERE)引擎 

解释posix
POSIX(Portable Operating System Interface)是Unix系统的一个设计标准。
当年最早的Unix,源代码流传出去了,加上早期的Unix不够完善,于是之后出现了好些独立开发的与Unix基本兼容但又不完全兼容的OS,通称Unix-like OS

两类、正则表达式符号

linux规范将正则表达式分为了两种

  • 基本正则表达式(BRE、basic regular expression)
BRE对应元字符有 
^ $ . [ ] *

其他符号是普通字符
; \
  • 扩展正则表达式(ERE、extended regular expression)
ERE在在BRE基础上,增加了
( ) { } ? + |  等元字符
  • 转义符
反斜杠 \
反斜杠用于在元字符前添加,使其成为普通字符

基本正则表达式(BRE)

测试文本数据

[root@yuchao-tx-server test]# cat chaoge666.txt
I am teacher yuchao.
I teach linux,python!

I like english

My website is http://yuchaoit.cn
Our school site is https://yuchao.com
My qq num is 877348180

Good good study , day day up!

关于单引号、双引号

  • 正则的模式,建议使用双引号
  • 如果未涉及变量等,用单引号也不影响

grep与正则


NAME
       grep, egrep, fgrep - print lines matching a pattern

SYNOPSIS
       grep [OPTIONS] PATTERN [FILE...]
       grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

例如传入的pattern(模式是) ,我们可以统称你写的正则是模式

^m,以m开头的行

[root@yuchao-tx-server test]# grep  -i -n  '^m' chaoge666.txt
6:My website is http://yuchaoit.cn
8:My qq num is 877348180

^ 尖角符

语法
写于最左侧,如
^yu 逐行匹配,找到以yu开头的内容

结合grep用法,-i 忽略大小写

image-20220403204344736

结合grep的参数 -o 只显示一行中匹配出来内容

image-20220403204511334

结合grep,过滤出以i开头的行,且显示行号

image-20220403204704501

$ 美元符

语法

word$ 匹配以word结尾的行

匹配所有以字符n结尾的行

image-20220403205308032

匹配所有以小数点. 结尾的行,这里因为.也有特殊作用,因此得使用单引号、或者转义符。

image-20220404110725626

单、双引号区别

变量解释

image-20250113220735158

^$ 匹配空行

找出文件的空行

image-20220404113514796

去掉空行,注释行

[root@www.yuchaoit.cn ~]$grep -Ev    '^$|^#' t_regex.txt
I am teacher yuchao.
I teach linux,python!
I like english
My website is http://yuchaoit.cn
Our school site is https://yuchao.com
My qq num is 877348180
my hobby is linux,game,movie..Python, life is short ,we need python..
hahahah n
xixixi  n..
Test data $name....



[root@www.yuchaoit.cn ~]$grep -v  '^$' t_regex.txt  | grep -v '^#'
I am teacher yuchao.
I teach linux,python!
I like english
My website is http://yuchaoit.cn
Our school site is https://yuchao.com
My qq num is 877348180
my hobby is linux,game,movie..Python, life is short ,we need python..
hahahah n
xixixi  n..
Test data $name....

. 点符

. 匹配除了换行符以外所有的内容、字符+空格,除了换行符。

. 点处理空格

. 可以匹配到空格,以及任意字符

但是点,不匹配换行符。

image-20220404114046906

. 匹配除换行符的所有字符

image-20220404114224722

. 代表任意一个字符

分别传入grep的模式

y.

y.. 任意2个字符

实践代码

image-20220404144715047

匹配符合模式.ac 的行

image-20220404150913337

.$ 匹配任意字符结尾

拿到每一行的结尾

image-20220404150208541

. 和转义符

只想拿到每一行结尾的普通小数点 .,需要对点转义

image-20220404150350485

\ 转义符

转义字符,让有特殊意义的字符,现出原形,还原其本义。

如
\.  还原为小数点

空格、换行、tab

https://deerchao.cn/tools/wegester/使用这个网址来测试换行符的匹配

image-20220410191538355


关于linux的换行符

image-20220410192210644


语法记忆

\b 匹配单词边界,如我想从字符串中“This is Regex”匹配单独的单词 “is” 正则就要写成 “\bis\b”

\n 匹配换行符 ,表示newline,向下移动一行,不会左右移动
\r 匹配回车符,表示return,回到当前行的最左边

linux换行符是\n,表示\r+\n 换行且回车,换行且回到下一行的行首


windows换行符是\r\n,表示回车+换行

\t 匹配一个横向的制表符,等于tab键

image-20220404152358185

* 星号

重复前一个字符0此或n次

image-20220404185819618

.* 符

匹配任意内容

.表示任意一个字符,*表示匹配前一个字符0次或多次

因此放一起,代表匹配每一行所有内容,包括空格

注意 . 点不匹配换行

image-20220404190557770

图解点 . 不匹配换行

首先,不匹配换行这事,是因为 . 的作用
.* 是重复前面这个字符0次或N次

image-20220408192027823

^.* 符

语法
^.* 表示以任意多个字符开头的行

基础用法,^.*

image-20220404191504690

找出任意以字母i开头的行,且匹配后续所有内容

image-20220404191101082

加大难度

找出任意以字母i开头的行,且以h结尾的行

image-20220404191228601

.*$ 符

以任意多个字符结尾的行

image-20220404191725480

你可以加上条件,例如p.*$

以p.*$结尾的行
等于、匹配出从p到结尾的所有内容

image-20220404191822956

[ ] 中括号

中括号,有如下用法

[abc]

[abc] 匹配括号内的小写a、b、c字符

关于到大小写的精准匹配,就别添加忽略大小写参数了

image-20220404193214895

[a-z]、 [A-Z] 、[a-zA-z]、[0-9]

[a-z]                匹配所有小写单个字母
[A-Z]                匹配所有单个大写字母
[a-zA-Z]        匹配所有的单个大小写字母
[0-9]                匹配所有单个数字
[a-zA-Z0-9]    匹配所有数字和字母

[a-z] 匹配小写字母

image-20220404195729328

[A-Z] 匹配大写字母

image-20220404195744056

[a-z0-9] 匹配小写字母和数字

image-20220404195849345

[0-9A-Z] 匹配大写字母和数字

image-20220404195920656

[a-z0-9A-Z] 匹配大写、小写字母、数字

image-20220404200002692

abc 中括号取反

语法

[^abc] 排除中括号里的a、b、c ,和单独的^符号,作用是不同的

[^a-z] 排除小写字母

image-20220404200623766

{ } 花括号(扩展正则)

在正则表达式中,a{n,m}是一种限定符的语法。它表示匹配前面的元素(这里是字符a)至少n次,最多m次。

例如,a{2,4}可以匹配aaaaaaaaa

a\{n,m\}

a\{n,m\} 重复字符a,n到m次

a\{1,3\} 重复字符a,1到3次


y{1,3}  # 重复这个y,最少一次,最大3次

实践

测试数据
[root@yuchao-tx-server test]# cat chaoge666.txt
I am teacher yuchao.
I teach linux,python!

I like english

My website is http://yuchaoit.cn
Our school site is https://yuchao.com
My qq num is 877348180

my qq num is not  87777773333344444888811188880000

Goog good study , day day up!

正则

8\{1,3\}
匹配数字8一次到3次

image-20220404201218034

每次最少找出2个8、最多3个8

8\{2,3\}

image-20220404201432127

grep 默认不认识扩展正则 {}

grep默认不认识扩展正则{},识别不到它的特殊作用,因此只能用转义符,让他成为有意义的字符。

image-20220404201813308

办法1
使用转义符 \{\}

办法2,让grep认识花括号,可以省去转义符
使用egrep命令
或者 grep -E

实践

image-20220404201955533

a\{n,\}

重复a字符至少n次,可以用简写了

image-20220404202208850

a\{n\}

重复字符a,正好n次。

image-20220404202332225

a\{,m\}

匹配字符a最多m次。

image-20220404202528175

扩展正则表达式(ERE)

这样记忆就好

  • 基本正则表达式
    • 属于早期正则表达式,支持一些基本的功能
    • 与grep、sed命令结合使用
  • 扩展正则表达式
    • 后来添加的正则表达式
    • 和egrep、awk命令结合

+ 加号

语法

+ 
重复前一个字符1次或多次

注意和*的区别,*是0次或多次

匹配一次或者多次0,没有0的行是不会显示的

0+

找出一个、或者多个数字零

image-20220405123257126

[0-9]+

从文中找出连续的数字,排除字母,特殊符号、空格

image-20220405123915904

[a-z]+

找出连续的小写字母、排除大写字母、标点符号、数字

image-20220405124233138

[A-Za-z0-9]+

注意,这里添加了+号,就是找的连续的字母数字了、缺少+号则是每次匹配单个字符

image-20220405124425616

[^A-Za-z0-9]+]

此写法,找出除了数字、大小写字母以外的内容,如空格、标点符号。

你可以使用-o参数,看到每次匹配的内容。

image-20220405124936650

*和+的区别

语法
*是重复0次、重复多次,因此没匹配到的行也过滤出来了

+是重复1次、多次、因此至少匹配到1次才看到

例如,我们来找到字母o,看如下2个写法

image-20220405125647057

go*d和go+d和go?d区别

准备测试数据

[root@yuchao-tx-server test]# cat god.log
I am God, I need you to good good study and day day up, otherwise I will send you to see Gd,oh sorry, gooooooooood!

关于寻找god、goooood、gd的区别

go*d 可以有0个或者n个字母o
go*d 可以找到god、good、gd、gooooooooood

go+d 可以有一个或n个字母o
go+d 可以找到god、good、gooooooooood

go?d  可以有0个或者1个字母0
go?d 可以找到gd、god

image-20220405132551007

| 或者符

竖线在正则里是或者的意思

查看内存信息

image-20220405133043311

查看文件系统inode和block信息

ext4文件系统

[242-yuchao-class01 root ~]#dumpe2fs /dev/sdc |grep -Ei '^(inode|block)'
dumpe2fs 1.42.9 (28-Dec-2013)
Inode count:              1310720
Block count:              5242880
Block size:               4096
Blocks per group:         32768
Inodes per group:         8192
Inode blocks per group:   512
Inode size:                  256

xfs文件系统

[242-yuchao-class01 root /mnt]#xfs_info /mnt |grep -E 'blocks.*imax.*|isize='
meta-data=/dev/sdd               isize=512    agcount=4, agsize=3276800 blks
data     =                       bsize=4096   blocks=13107200, imaxpct=25

找出文件中的空行以及注释行

测试数据

[root@yuchao-tx-server test]# cat chaoge666.txt 
I am teacher yuchao.
I teach linux,python!

I like english

My website is http://yuchaoit.cn
Our school site is https://yuchao.com
My qq num is 877348180

my qq num is not  87777773333344444888811188880000

#Goog good study , day day up!
#
#hello  halo

image-20220405150556440

( ) 括号、分组符

语法
() 作用是将一个或者多个字符捆绑在一起,当做一个整体进行处理

小括号功能之一是分组过滤被括起来的内容,括号内的内容表示一个整体

括号()内的内容可以被后面的"\n"正则引用,n为数字,表示引用第几个括号的内容

() () () 
\1:表示从左侧起,第一个括号中的模式所匹配到的字符
\2:从左侧起,第二个括号中的模式所匹配到的字符
\3

分组基本用法

测试数据
[root@yuchao-tx-server test]# cat god.log
I am God, I need you to good good study and day day up, otherwise I will send you to see Gd,oh sorry, gooooooooood!
I am glad to see you, god,you are a good god!

要求仅仅匹配出glad和good

尝试使用正则
grep -iE "gla|ood" god.log

image-20220405173609202

并非我们想要的数据
我想要的是例如这样的匹配,只找出good、glad
grep -iE "glad|good" god.log

image-20220405173646473

可以使用分组写法

grep -iE "g(la|oo)d" god.log

image-20220405173816906

分组与向后引用

语法
()      
分组过滤,被括起来的内容表示一个整体,另外()的内容可以被后面的\n引用,n为数字,表示引用第几个括号的内容

\n      
引用前面()里的内容,例如(abc)\1 表示匹配abcabc

测试数据

[root@yuchao-tx-server test]# cat lovers.log
I like my lover.
I love my lover.
He likes his lovers.
He love his lovers.

分组正则,提取love出现2次的行。

拆解
love,可以写为l..e

image-20220405175634324

提取/etc/passwd

找出系统中几个特殊shell、专门用来开机,关机的用户
特点是、用户名、登录shell名字一样
可以用分区提取出

image-20220405175835135

分组正则,提取特殊用户

这部分正则需要拆开,更容易理解
1.提取冒号以外的字符,使用+可以匹配更多字母,没必要每次只处理一个
grep -Ei "[^:]+" /etc/passwd

2. 使用\b匹配单词边界,提取出单词,示例用法,通常英文单词的边界是空格,标点符号
[root@yuchao-tx-server test]# echo  'my name is chao,everyone call me chaoge' | grep -Ei "chao\b" -o
chao

3.继续提取用户文件,来确定第一个单词的边界

image-20220405183453377

完整图解

image-20220405184538736

更简单的写法,多次分组

image-20220411163812863

分组综合练习

以下是使用 grep 演示正则分组的几个案例:

案例一:提取 IP 地址的各个部分

假设你有一个文件 ips.txt 包含多个 IP 地址,如下:

192.168.1.1
10.0.0.1
172.16.0.1

你可以使用 grep 和正则分组来提取每个 IP 地址的四个部分:

grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' ips.txt | grep -Eo '([0-9]{1,3})'

解释

  • grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' ips.txt
    • -E 表示使用扩展正则表达式。
    • -o 表示只输出匹配的部分,而不是整行。
    • ([0-9]{1,3}\.){3}[0-9]{1,3} 是一个正则表达式,它匹配 IP 地址的模式:
      • ([0-9]{1,3}\.){3} 匹配三个数字加一个点的序列(例如 192.168.1.)。
      • [0-9]{1,3} 匹配最后一组数字(例如 1)。
  • grep -Eo '([0-9]{1,3})':对前面的结果再次使用 grep 提取每个数字部分。

案例二:提取 HTML 标签的内容

假设你有一个文件 html.txt 包含一些 HTML 内容,如下:

<p>This is a paragraph</p>
<div>Some content</div>
<span>Another element</span>

提取标签内容。

正则表达式总结

基础正则 BRE
^ 
$ 
. 
*
.*
[abc]
[^abc]
\{n,m\}

BRE语法

. 匹配单个任意字符, 匹配 . 本身使用 \.

* 前面的字符或模式重复任意次,匹配 * 本身使用 \*

\{m\} 前面的字符或模式重复m次

\{m,n\} 前面的字符或模式重复m到n次

\{m,\} 前面的字符或模式重复m次及以上

\(regexp\) 分组,将 \(\) 之间的内容视为一个整体,有两个作用

  1. 配合前面的 * \{m,n\} 等量词使用,例如: ab\{2\} 匹配“abb”, 而 \(ab\)\{2\} 匹配“abab”
  2. 向后引用(back references),使用 \1 ~ \9 来引用第1~9个分组匹配的内容
  3. 例如: \(ab*\)\1 可以匹配“abab”,也能匹配“abbbabbb”

^ 放在正则表达式开头则匹配行首,其他位置匹配 ^ 本身

$ 放在正则表达式末尾则匹配行尾,其他位置匹配 $ 本身

[list] 自定义字符集,可以匹配 [] 之间出现的任意字符,例如: a[bcd] 可以匹配”ab",“ac”或“ad”。

且支持使用char1-char2这种省略写法,例如: [0-9]* 可以匹配”1234567890“ , [a-c]* 可以匹配“cabba”

[^list] 同上,^取反的作用,匹配所有没有出现在 [] 之间的其他字符

另外其他风格的正则表达式中有诸如 \d \w \s 等速记符号(shorthand)表示一些常用字符集,BER和ERE均不支持这种写法,取而代之的是POSIX标准中定义的字符集:

POSIX正则语法表

POSIX Description ASCII Shorthand
[:alnum:] 数字和字母 [a-zA-Z0-9]
[:alpha:] 字母 [a-zA-Z]
[:ascii:] ASCII字符 [\x00-\x7F]
[:blank:] 空格和 Tab [ \t] \h
[:cntrl:] 控制字符 [\x00-\x1F\x7F]
[:digit:] 数字 [0-9] \d
[:graph:] 可视字符 [\x21-\x7E]
[:lower:] 小写字母 [a-z] \l
[:print:] 可打印字符 [\x20-\x7E]
[:punct:] 标点符号 [!"#$%&'()*+, -./:;<=>?@[ ]^_‘{\ }~]
[:space:] 所有空白字符 [ \t\r\n\v\f] \s
[:upper:] 大写字母 [A-Z] \u
[:word:] 单词 [A-Za-z0-9_] \w
[:xdigit:] 十六进制数 [A-Fa-f0-9]
注意:[ 和 ] 也是该字符集名称的一部分,即在使用中和 [0-9] 等价的是 [[:digit:]] 而不是 [:digit:]

ERE语法

ERE和BRE的最显著的区别是ERE中所有元字符(metacharacters)均不需要使用 \ 进行转义,即用 {m,n} 替代 \{m,n\} , (regexp) 替代 \(regexp\) (当然分组向后引用依旧是 \1 ~ \9)。

此外ERE还在BRE基础上增加了以下语法:

? 前面的字符或模式重复0或1次

+ 前面的字符或模式重复1次及以上

|,regexp1|regexp2匹配regexp1regexp2

GNU扩展的BRE

实际上现代Linux发行版中使用的 grep sed awk 等工具均由GNU提供,GNU在实现时对BRE进行了扩展,增加了 \? \+ \| 使得BRE和ERE的区别仅剩元字符是否需要转义

个人认为BRE现在存在的主要意义还是向下兼容,避免修改已经投入使用的正则表达式。

正则官网讲解

参考官网文档,拿到最精准的解释

https://www.regular-expressions.info/posix.html
https://www.regular-expressions.info/posixbrackets.html
https://www.gnu.org/software/sed/manual/html_node/BRE-syntax.html#BRE-syntax

总结grep

  • egrep被淘汰,使用grep -E
  • 可以是用grep -o参数,查看每次匹配的结果
  • 正则需要在练习中理解其含义,无法死记硬背
  • 后面结合sed、awk发挥更多正则作用

正则记忆表

image-20220405213956490


image-20220405214008926


image-20220405214019278

可以用于在线测试正则的网站

https://deerchao.cn/tools/wegester/

Copyright © www.yuchaoit.cn 2025 all right reserved,powered by Gitbook作者:于超 2025-01-14 17:16:41

results matching ""

    No results matching ""