shell 编程之正则表达式与文本处理器

发布于:2025-04-18 ⋅ 阅读:(68) ⋅ 点赞:(0)

目录

一、正则表达式

1. 概念

2. 作用

3. 分类

二、基础正则表达式(BRE)

三、扩展正则表达式(ERE)

四、文本处理器

1. sed 工具

2. awk 工具

五、总结

总结对比

元字符总结

工具对比与选择指南


一、正则表达式

1. 概念

正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串,简单来说,是一种匹配字符串的方法,通过一些特殊符号,实现快速查找、删除、替换某个特定字符串。

2. 作用

正则表达式主要用于文本搜索、替换和字符串操作,例如在grep、awk、sed等命令中广泛应用,以实现对文本的高效处理。

3. 分类

  • 基础正则表达式(grep 、sed)
  • 扩展正则表达式(egrep 简化操作、范围更广 awk)

4.应用场景

文本搜索、数据清洗、日志分析、表单验证等。

二、基础正则表达式(BRE)

支持基本元字符(^$.*[]

grep 命令选项

选项

说明

-a

不要忽略二进制数据

-A <显示列数>

除了显示符合范本样式的那一行之外,并显示该行之后的内容

-b

在显示符合范本样式的那一行之外,并显示该行之前的内容

-c

计算符合范本样式的列数

-C <显示列数> 或 -< 显示列数 >

除了显示符合范本样式的那一列之外,并显示该列之前后的内容

-d <进行动作>

当指定要查找的是目录而非文件时,必须使用这项参数,否则 grep 命令将回报信息并停止动作

-e <范本样式>

指定字符串作为查找文件内容的范本样式

-E

将范本样式为延伸的普通表示法来使用,意味着使用能使用扩展正则表达式

-f <范本文件>

指定范本文件,其内容有一个或多个范本样式,让 grep 查找符合范本条件的文件内容,格式为每一列的范本样式

-F

将范本样式视为固定字符串的列表

-G

将范本样式视为普通的表示法来使用

-h

在显示符合范本样式的那一列之前,不标示该列所属的文件名称

-H

在显示符合范本样式的那一列之前,标示该列的文件名称

-i

忽略字符大小写的差别

-l

列出文件内容符合指定的范本样式的文件名称

-L

列出文件内容不符合指定的范本样式的文件名称

-n

在显示符合范本样式的那一列之前,标示出该列的编号,显示行数

-q

不显示任何信息

-R/-r

此参数的效果和指定 “-d recurse” 参数相同

-s

不显示错误信息

-v

反转查找

-w

只显示全字符合的列

-x

只显示全列符合的列

-y

此参数效果跟 “-i” 相同

-o

只输出文件中匹配到的部分

常用元字符

元字符 描述 示例与解释
^ 匹配行首 ^start → 匹配以 "start" 开头的行
$ 匹配行尾 end$ → 匹配以 "end" 结尾的行
. 匹配任意单个字符(换行符除外) a.c → 匹配 "abc"、"aXc"
* 匹配前一个字符 0 次或多次 go*gle → 匹配 "ggle"、"gogle"、"google"
[] 匹配字符集合中的任意一个字符 [aeiou] → 匹配任意元音字母
[^] 排除字符集合中的字符 [^0-9] → 匹配非数字字符
{ } 查找连续字符的范围,使用“转义符\” o\{2\} →查找两个o的字符
\ 转义特殊字符 \. → 匹配字面量 .

注意:

“^”符号在元字符集合“[]”符号内外的作用是不一样的,在“[]”符号内表示反向选择,在“[]”
符号外则代表定位行首
示例:
grep -in 'the' test.txt       //查找出特定字符“the”所在位置(-n”表示显示行号、“-i”表示不区分大小写)
grep -vn 'the' test.txt       //查找不包含“the”字符的行
grep -n 'sh[io]rt' test.txt   //同时查找到“shirt”与“short”这两个字符串
grep -n '^[a-z]' test.txt      //查询以小写字母开头的行
grep -n '[^w]oo' test.txt    //查找“oo”前面不是“w”的字符串
grep -n '\.$' test.txt   //以点结尾的行,转义符将特殊意义字符转化成普通字符
grep -n '^$' test.txt   //查询空白行

grep -n 'woo*d' test.txt  //查询以 w 开头 d 结尾,中间包含至少一个 o 的字符串
grep -n 'w.*d' test.txt   //查询以 w 开头 d 结尾,中间的字符可有可无的字符串
grep -n '[0-9][0-9]*' test.txt  //查询任意数字所在行
grep -n 'o\{2\}' test.txt   //查询两个 o 的字符
grep -n 'wo\{2,5\}d' test.txt  //查询以 w 开头以 d 结尾,中间包含 2~5 个 o 的字符串
grep -n 'wo\{2,\}d' test.txt  //查询以 w 开头以 d 结尾,中间包含 2 个或 2 个以上 o 的字符串

三、扩展正则表达式(ERE)

与 BRE 的区别

  • 语法更简洁: 在BRE 基础上增加 +?|(){} 等元字符。无需转义

  • 启用方式:需在命令中加 -E 选项(如 grep -E 或 egrep)。

元字符 描述 示例与解释
+ 匹配前一个字符 1 次或多次 go+gle → 匹配 "gogle"、"google"
? 匹配前一个字符 0 次或 1 次 colou?r → 匹配 "color" 或 "colour"
|

逻辑或

`cat|dog` → 匹配 "cat" 或 "dog"
( ) 查找“组”字符串
t(a|e)st   查询"tast"或者"test"字符串
( )+ 辨别多个重复的组
egrep -n 'A(xyz)+C' test.txt”。
该命令是查询开头的"A"结尾是"C",中间有一个以上的"xyz"字符串的意思

四、文本处理器

1. sed 工具

  • 功能:文本解析转换工具,可以读取文本,支持查找、替换、删除、插入操作。

  • 语法sed [选项] '命令' 文件参数

  • 工作流程

    读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓
    冲区中(又称模式空间,pattern space)。
    执行:默认情况下,所有的 sed 命令都在模式空间中顺序地执行,除非指定了行
    的地址,否则 sed 命令将会在所有的行上依次执行。
    显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空

注意:  默认情况下所有的 sed 命令都是在模式空间内执行的,因此输入的文件并

不会发生任何变化,除非是用重定向存储输出。

常用选项

描述

-n (--quiet 或 silent)

仅显示处理后的结果

-i

直接修改文件内容(慎用!)

-e(--expression)

执行多条命令

 -h (--help) 

显示帮助 

-f  (--file)
表示用指定的脚本文件来处理输入的文本文件
地址定界 描述
n 第 n 行
$ 最后一行
/pattern/ 匹配模式的行
n,m 从第 n 行到第 m 行
常用命令 描述
s/old/new/ 替换第一个匹配的字符串
s/old/new/g 替换所有匹配的字符串
p 打印行(常与 -n 联用)
s
替换,替换指定字符
c

替换,整行或整块

y 字符转换
d 删除行
a 在行后追加文本
i 在行前插入文本
迁移文本参数
说明
H 复制到剪贴板
g、G
将剪贴板中的数据覆盖/追加至指定行
w 保存为文件
r 读取指定文件
a 追加指定内容

示例:

(1)输出符合条件的文本
sed -n 'p' test.txt
//输出所有内容,等同于 cat test.txt
sed -n 'p;n' test.txt 
//输出所有奇数行,n 表示读入下一行资料
sed -n 'n;p' test.txt
 //输出所有偶数行,n 表示读入下一行资料
sed -n '10,${n;p}' test.txt 
//输出第 10 行至文件尾之间的偶数行
sed -n '/the/p' test.txt 
//输出包含 the 的行
sed -n '/the/=' test.txt 
 //输出包含 the 的行所在的行号,等号(=)用来输出行号
sed -n '/[0-9]$/p' test.txt
//输出以数字结尾的行
sed -n '/^PI/p' test.txt 
//输出以 PI 开头的行
sed -n '/\<wood\>/p' test.txt 
 //输出包含单词 wood 的行,\<、\>代表单词边界

(2)删除符合条件的文本( nl 命令用于计算文件的行数)
nl test.txt | sed '3d' 
//删除第 3 行
nl test.txt |sed '/cross/d' 
//删除包含 cross 的行,原本的第 8 行被删除;如果要删除不包含 cross 的行,用!符号表示取反操作, 如'/cross/!d'
sed '/^[a-z]/d' test.txt 
//删除以小写字母开头的行
sed '/^$/d' test.txt 
//删除所有空行

(3)替换符合条件的文本
sed 's/the/THE/' test.txt 
//将每行中的第一个 the 替换为 THE
sed 's/l/L/2' test.txt
 //将每行中的第 2 个 l 替换为 L
sed 's/the/THE/g' test.txt 
//将文件中的所有 the 替换为 THE
sed 's/o//g' test.txt 
//将文件中的所有 o 删除(替换为空串)
sed 's/^/#/' test.txt 
//在每行行首插入#号
sed '/the/s/^/#/' test.txt 
//在包含 the 的每行行首插入#号
sed 's/$/EOF/' test.txt
 //在每行行尾插入字符串 EOF
sed '3,5s/the/THE/g' test.txt 
//将第 3~5 行中的所有 the 替换为 THE
sed '/the/s/o/O/g' test.txt 
//将包含 the 的所有行中的 o 都替换为 O

(4)迁移符合条件的文本
sed '/the/{H;d};$G' test.txt 
//将包含 the 的行迁移至文件末尾,{;}用于多个操作
sed '1,5{H;d};17G' test.txt 
//将第 1~5 行内容转移至第 17 行后
sed '/the/w out.file' test.txt 
//将包含 the 的行另存为文件 out.file
sed '/the/r /etc/hostname' test.txt
 //将文件/etc/hostname 的内容添加到包含 the 的每行以后
sed '3aNew' test.txt 
//在第 3 行后插入一个新行,内容为 New
sed '/the/aNew' test.txt
 //在包含 the 的每行后插入一个新行,内容为 New
sed '3aNew1\nNew2' test.txt 
//在第 3 行后插入多行内容,中间的\n 表示换行
注 意 : 若 是 删 除 重 复 的 空 行 , 即 连 续 的 空 行 只 保 留 一 个 , 执 行 “sed
-e‘/^$/{n;/^$/d}’test.txt”命令即可实现。其效果与“cat -s test.txt”相同,n 表示读下一行数
据。

2. awk 工具

  • 功能:文本分析工具,支持按字段处理、计算、格式化输出。

  • 语法

    awk 选项 '模式或条件 {编辑指令}' 文件 1 文件 2 …  //过滤并输出文件中符合条件的内容
    awk -f 脚本文件 文件 1 文件 2      //从脚本中调用编辑指令,过滤并输出内容
  • 注意

    在使用 awk 命令的过程中
    可以使用逻辑操作符“&&”表示“与”、“||”
    表示“或”、“!”表示“非”;还可以进行的数学运算

内建变量

作用
$0 当前整行内容
$n
当前处理行的第 n 个字段(第 n 列)
FS
指定每行文本的字段分隔符,默认为空格或制表位
NF 当前行的字段数
NR

当前处理的行号

RS
数据记录分隔,默认为\n,即每行为一条记录
FILENAME
被处理的文件名

示例

(1)按行输出文本
awk '{print}' test.txt 
//输出所有内容,等同于 cat test.txt
awk '{print $0}' test.txt 
//输出所有内容,等同于 cat test.txt
awk 'NR==1,NR==3{print}' test.txt 
//输出第 1~3 行内容
awk '(NR>=1)&&(NR<=3){print}' test.txt 
//输出第 1~3 行内容
awk 'NR==1||NR==3{print}' test.txt 
//输出第 1 行、第 3 行内容
awk '(NR%2)==1{print}' test.txt 
//输出所有奇数行的内容
awk '(NR%2)==0{print}' test.txt
 //输出所有偶数行的内容
awk '/^root/{print}' /etc/passwd 
//输出以 root 开头的行
awk '/nologin$/{print}' /etc/passwd 
//输出以 nologin 结尾的行
awk 'BEGIN {x=0};/\/bin\/bash$/{x++};END {print x}' /etc/passwd
//统计以/bin/bash 结尾的行数,等同于 grep -c "/bin/bash$" /etc/passwd
awk 'BEGIN{RS=""};END{print NR}' /etc/squid/squid.conf
//统计以空行分隔的文本段落数

(2)按字段输出文本
awk '{print $3}' test.txt
 //输出每行中(以空格或制表位分隔)的第 3 个字段
awk '{print $1,$3}' test.txt 
//输出每行中的第 1、3 个字段
awk -F ":" '$2==""{print}' /etc/shadow 
//输出密码为空的用户的 shadow 记录
awk 'BEGIN {FS=":"}; $2==""{print}' /etc/shadow
//输出密码为空的用户的 shadow 记录
awk -F ":" '$7~"/bash"{print $1}' /etc/passwd
//输出以冒号分隔且第 7 个字段中包含/bash 的行的第 1 个字段
awk '($1~"nfs")&&(NF==8){print $1,$2}' /etc/services
//输出包含 8 个字段且第 1 个字段中包含 nfs 的行的第 1、2 个字段
awk -F ":" '($7!="/bin/bash")&&($7!="/sbin/nologin"){print}' /etc/passwd
//输出第 7 个字段既不为/bin/bash 也不为/sbin/nologin 的所有行

(3)通过管道、双引号调用 Shell 命令
awk -F: '/bash$/{print | "wc -l"}' /etc/passwd
//调用 wc -l 命令统计使用 bash 的用户个数,等同于 grep -c "bash$" /etc/passwd
awk 'BEGIN {while ("w" | getline) n++ ; {print n-2}}'
 //调用 w 命令,并用来统计在线用户数
awk 'BEGIN { "hostname" | getline ; print $0}'
 //调用 hostname,并输出当前的主机名

五、总结

总结对比

工具/语法 核心用途 典型场景
BRE 基本模式匹配 简单文本搜索、grep 默认模式
ERE 复杂模式匹配(支持逻辑、分组) 提取结构化数据(IP、邮箱)
sed 文本替换、删除、插入 批量修改配置文件、清理数据
awk 字段处理、数据计算、报表生成 日志分析、统计汇总

元字符总结

元字符 作用

^

匹配行首

$

匹配行尾

.

匹配任意单个字符(除换行符)

*

匹配前一个字符 零次或多次

[]

字符范围,匹配字符集合中的任意一个

\

转义符

+

匹配前面的子表达式一次或多次
匹配前面的子表达式零次或一次
{n} n是一个非负整数,匹配确定的n次
{n,m}

n,m是非负整数,其中n <= m.最少匹配n次且最多匹配m次

{n,} n是一个非负整数,至少匹配n次
\d 匹配一个数字字符
\D 匹配一个非数字字符
\s 匹配任何空白字符
\S 匹配任何非空白字符
\w 匹配字母、数字、下划线
\W 匹配非字母、数字、下划线
\n  匹配一个换行符
\f 匹配一个换页符
\r 匹配一个回车符

工具对比与选择指南

场景 推荐工具 理由
简单文本替换 sed 语法简洁,适合单行操作
复杂字段处理与计算 awk 内置字段分割和数学运算
多条件逻辑处理 awk 支持 if/else、循环等编程结构
批量删除或插入行 sed 地址定界和命令组合灵活
数据统计与报表生成 awk 可汇总数据并格式化输出

常见问题与调试技巧

1. 正则表达式不匹配

  • 检查特殊字符转义:如 *.() 在 BRE 中需转义。

  • 使用扩展模式:如 grep -E 或 sed -r 启用 ERE。

2. sed 修改文件无效

  • 确认 -i 选项:无 -i 选项时仅输出到屏幕,不修改原文件。

  • 备份原文件sed -i.bak 's/old/new/' file 生成 file.bak 备份。

3. awk 字段分割异常

  • 指定分隔符:用 -F 明确分隔符(如 -F':')。

  • 处理空白行:添加 NF > 0 条件过滤空行。

4. 性能优化

  • 减少管道操作:合并多个 sed 或 awk 命令为单次处理。

  • 避免频繁读写文件:使用内存处理或临时文件。