正则表达式基础

介绍

在 Shell 编程中,正则表达式(Regular Expression)和文本处理器(如 grep, sed, awk 等)是两个极其重要的工具,它们允许我们以复杂且高效的方式搜索、处理和操作文本数据。本博客将简要介绍 Shell 编程中正则表达式的使用,并展示如何使用 grep, sed, 和 awk 这三个强大的文本处理器。

正则表达式

什么是正则表达式呢?

正则表达式,又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(英语:Regular Expression,在代码中常简写为 regex、regexp 或 RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。

 基础正则表达式

基础正则表达式是常用正则表达式最基础的部分。在 Linux 系统中常见的文件 处理工具中 grep sed 支持基础正则表达式,而 egrep awk 支持扩展正则表达式。

 正则表达式grep

grep 是 Unix/Linux 系统中一个强大的命令行文本搜索工具,全称为 Global Regular Expression Print。它的核心功能是通过正则表达式(Regular Expression, Regex)在文件或输入流中快速匹配并输出符合条件的文本行。

1.grep的基本用法

grep [选项] "正则表达式模式" 文件名

  • 默认行为:输出包含匹配模式的行。
  • 无文件名时:从标准输入(如管道)读取数据。 

简单示例:

grep "error" log.txt        #在log.txt 中查找包含 "error"的行

 2.grep支持的正则表达式的类型

grep 默认支持基础正则表达式(Basic Regular Expression, BRE),若需使用更强大的扩展正则表达式(Extended Regular Expression, ERE),需添加 -E 选项或使用 egrep 命令。

类型 语法支持 启用方式 示例
BRE 基础正则(需转义’+,?,等) 默认 grep "a\{2\}" file(匹配连续两个a)
ERE 扩展正则(直接使用'+,?,等) grep -E或egrep egrep "a{2}" file

3.常用正则表达式语法(以ERE为例)

1.字符匹配

  • . :匹配a,b或c。
  • [^abc]:匹配非a,b,c的字符。
  • \d:匹配数字(需注意:grep默认不支持\d,需用[0-9]或[:digit:])

2.锚点(定位符)

  • ^:匹配行首。
  • $:匹配行尾。
  • \<和\>:匹配单词的边界(如\hello\>匹配独立单词"hello")

3.量词

  • *:前一个字符出现0次或多次。

  • +重复一个或者一个以上的前一个字符

  • ?零个或者一个的前一个字符

  • {n}:精确匹配n次。

  • {n,}:至少匹配n次。

  • {n,m}:匹配n到m次。

4.分组与逻辑

  • ():查找组字符串。
  • ()+:辨别多个重复组。
  • |:逻辑“或”(需-E)。

5.预定义字符类

  • [:alnum:]:字母和数字。
  • [:alpha:]:字母。
  • [:digit:]:数字。
  • [:lower:]:小写字母。
  • [:upper:]:大写字母。

4.grep的常用选项


选项 功能 示例
-i 忽略大小写 grep -i "Error" file
-v 反向匹配(输出不匹配的行) grep -v "success" file
-o 仅输出匹配的文本(而非整行) grep -o "\d{3}" file
-n 显示匹配行的行号 grep -n "error" file
-c 统计匹配行的数量 grep -c "warning" file
-r或-R 递归搜索目录下的所有文件 grep -r "pattern" /path/to/dir
-A num 输出匹配行及之后 num 行 grep -A 2 "error" file
-B num 输出匹配行及之前 num 行 grep -B 2 "error" file
-C num 输出匹配行及前后各 num 行 grep -C 2 "error" file

 5.应用示例

1.查找包含特定单词的行

grep "apple" fruits.txt        #查找包含"apple"的行

grep -i "Apple" fruits.txt        #忽略大小写

2.使用量词匹配多个字符

egrep "go{2}d" file        # 匹配 "good"(o 出现 2 次)
egrep "a+b" file           # 匹配 "ab", "aab", "aaab" 等

 3.匹配行首/行尾

grep "^start" file         # 匹配以 "start" 开头的行
grep "end$" file           # 匹配以 "end" 结尾的行

4.分组与逻辑或 

grep "^start" file         # 匹配以 "start" 开头的行
grep "end$" file           # 匹配以 "end" 结尾的行

5.提取特定格式的数据 

# 提取 IP 地址(简单示例)
egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}" access.log

6.反向匹配排除内容 

grep -v "#" config.conf    # 排除注释行(以 # 开头)

7.统计错误日志出现次数 

grep -c "ERROR" app.log    # 统计 "ERROR" 出现的行数

 文本处理器sed

sed是一个强大而简单的文本解析转换工具,可以读取文本,并根据指定的条件对文本进行编辑(删除,替换,添加,移动等),最后输出所有行或者仅输出处理的某些行。sed也可以在无交互的情况下实现相当复杂的文本处理操作,被广泛应用于Shell脚本中,用以完成各种自动化处理任务。

sed的工作流程主要包括读取,执行和显示三个过程。

  • 读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)。

  • 执行:默认情况下,所有的 sed 命令都在模式空间中顺序地执行,除非指定了行的地址,否则 sed 命令将会在所有的行上依次执行。

  • 显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。

1.sed的基本语法

sed [选项] '命令' 文件名

 常用选项:


选项 说明
-n

使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。

-i

直接修改读取的文件内容,而不是输出到终端。

-e

直接在命令列模式上进行 sed 的动作编辑

-f

直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作

-r

sed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法)

2.常用sed命令

1.替换命令s

  • 语法:s/旧模式/替换内容/[修饰符]
  • 功能:替换匹配到的文本。
  • 修饰符:
    • g:全局替换(一行中所有匹配项)。
    • i:忽略大小写。
    • p:替换后打印行(需配合-n选项)

示例:

sed 's/old/new/' file.txt        # 每行第一个 "old" 替换为 "new"
sed 's/old/new/g' file.txt       # 替换所有 "old" 为 "new"
sed 's/old/new/2' file.txt       # 每行第二个 "old" 替换为 "new"
sed 's/old/new/gi' file.txt      # 全局替换,忽略大小写

2.删除命令d 

  • 语法:[地址范围]d
  • 功能:删除匹配的行。

示例:

sed '3d' file.txt                # 删除第3行
sed '/pattern/d' file.txt        # 删除包含 "pattern" 的行
sed '1,5d' file.txt              # 删除1到5行

3.打印命令p 

  • 语法:[地址范围]p。
  • 功能:显示打印匹配的行(需配合-n选项)。

示例:

sed -n '3p' file.txt             # 仅打印第3行
sed -n '/pattern/p' file.txt     # 打印包含 "pattern" 的行

4.插入/追加命令i和a 

  • 语法:
    • i\插入内容:在匹配行前插入内容。
    • a\追加内容:在匹配行后追加内容。

示例:

sed '3i\插入内容' file.txt        # 在第3行前插入一行 "插入内容"
sed '/pattern/a\追加内容' file.txt # 在匹配行后追加一行

5.文件写入命令w 

  • 语法:[地址范围]w 文件名。
  • 功能:将匹配的行写入指定文件。

示例:

sed '/error/w error.log' app.log  # 将包含 "error" 的行写入 error.log

3.sed的地址范围 

地址范围用于限定命令作用的行,可以是行号或正则表达式匹配。

1.单行地址

  • 行号:sed '5s/old/new/'(仅第五行)。
  • 正则匹配:sed '/pattern/s/old/new/'(匹配pattern的行)。

2.多行范围

  • 行号范围:sed '2,5d'9(删除2到5行)。
  • 正则范围:sed '/start/,/end/d'(删除从匹配start到end的行)。

3.特殊符号

  • $:最后一行(如sed '$d'删除最后一行)。
  • +N:相对行号(如sed '2,+3d' 删除第2行及之后3行)

4.结合正则表达式

sed默认支持基础正则表达式(BRE),通过-r-E启用扩展正则表达式(ERE)。

常见用法:

  • 替换日期格式:

sed -r 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\2\/\3\/\1/' dates.txt

将YYYY-MM-DD转换为MM/DD/YYY

  •  删除空行:

sed '/^$/d' file.txt            # 删除所有空行

  • 提取特定内容: 

sed -n 's/.*Name: \(.*\) Age:.*/\1/p' data.txt

提取 "Name:"后的名字(假设格式为Name:Alice Age:30)。

文本处理器awk

AWK 是一种优良的文本处理工具。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。最简单地说,AWK 是一种用于处理文本的编程语言工具。

核心特点:

  • 字段处理:自动分隔行到字段,支持自定义分隔符。
  • 内置变量:如NR(当前行号),NF(当前行的字段数),FS(字段分隔符)等。
  • 数学运算:直接支持算术和统计操作(如求和,平均值)。
  • 关联数组:支持复杂数据结构的存储和操作。

1.awk的基本语法

awk '模式 {动作}’ 文件名

或编写多行脚本:

 awk -f script.awk 文件名

常用选项: 

选项 说明
-F

指定字段分隔符(如-F:,-F',')

-v 定义变量(如-v var=valur)
-f 从脚本文件读取命令

2.awk的常用模式与动作

1.默认行为(无模式)

awk '{print $0}' file.txt    # 打印所有行(等价于 `cat`)

2.按行号过滤 

awk 'NR == 3' file.txt       # 打印第3行
awk 'NR >= 2 && NR <=5' file # 打印第2到5行

3.按字段值过滤 

awk '$1 == "root"' /etc/passwd   # 第1列为 "root" 的行
awk '$3 > 1000' /etc/passwd      # 第3列大于1000的行

4.正则表达式匹配 

awk '/error/ {print $2}' log.txt         # 匹配含 "error" 的行,打印第2列
awk '$1 ~ /^192\.168/ {print $0}' ips.txt # 第1列以 "192.168" 开头的行

3.内置变量 

$0 表示整个当前行
$1 每行的第一个字段
NF 字段数量变量
BR 每行的记录号,多文件记录递增
FNR 与NR类似,不过多文件记录不递增,每个文件都从1开始
\t 制表符
\n 换行符
FS BEGIN时定义分隔符
RS 输入的记录分隔符,默认为换行符(即文本是按一行一行输入)
~ 匹配,与==相比不是精确比较
!~ 不匹配,不精确比较
== 等于,必须全部相等,精确比较
!= 不等于,精确比较
&& 逻辑与
|| 逻辑或
+ 匹配时表示1个或1个以上
/[0-9][0-9]*/ 两个或两个以上数字
/[0-9][0-9]*/ 一个或一个以上数字
FILENAME 文件名
OFS

输出字段分隔符,默认也是空格,可以改为制表符等

ORS 输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕
-F'[:#/]' 定义三个分隔符

4.常用操作示例

1.打印特定列

awk '{print $1, $3}' file.txt           # 打印第1列和第3列(默认空格分隔)
awk -F':' '{print $1, $7}' /etc/passwd  # 以冒号分隔,打印用户名和Shell

 2.自定义输出格式

awk '{printf "User: %-10s UID: %d\n", $1, $3}' /etc/passwd

3.条件过滤 

# 筛选第2列大于50的行
awk '$2 > 50 {print $1, $2}' data.txt
# 结合逻辑运算符
awk '$1 == "admin" && $3 != "0" {print $0}' users.txt

4.统计与计算 

# 计算第1列的总和
awk '{sum += $1} END {print sum}' data.txt
# 计算平均值
awk '{sum += $1; count++} END {print sum/count}' data.txt
# 统计每列的最大值
awk 'NR==1 {max=$1} $1>max {max=$1} END {print max}' data.txt

5. 文本处理

# 替换文本
awk '{gsub("old", "new"); print}' file.txt
# 提取IP地址
awk '{match($0, /([0-9]{1,3}\.){3}[0-9]{1,3}/); print substr($0, RSTART, RLENGTH)}' log.txt

6.使用关联数组 

# 统计单词频率
awk '{for (i=1; i<=NF; i++) count[$i]++} END {for (word in count) print word, count[word]}' text.txt

你可能感兴趣的:(正则表达式)