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

Shell编程之正则表达式与文本

目录

一 正则表达式

1 正则表达式的定义

2 正则表达式用途

二 正则表达式类型

1 基础正则表达式示例

(1)查找特定字符

(2)利用中括号” [] “来查找集合字符

(3)查找行首” ^ “与行尾字符”$“

(4)查找任意一个字符” .“ 与重复字符”*“

(5)查找连续字符范围”{}“

2 元字符总结

3 扩展正则表达式

4 扩展正则表达式和基础正则表达式的对比总结

三 文本处理器

1 sed工具

(1)输出符合条件的文本(p表示正常输出)

(2)删除符合条件的文本(d)

(3)替换符合条件的文本

(4)迁移符合条件的文本

(5)使用脚本编辑文件

(6)sed直接操作文件示例

2 awk工具

(1)按行输出文本

(2)按字段输出文本

(3)通过管道,双引号调用shell命令

3 sed工具和awk工具的对比总结


一 正则表达式

1 正则表达式的定义

正则表达式(Regular Expression,简称 regex 或 regexp)是一种用于描述字符串匹配规则的文本模式。它由普通字符(如字母、数字)和元字符(特殊符号)组成,通过特定的语法规则实现对字符串的搜索、匹配、替换或提取等操作。

核心特点

  • 是一种迷你语言,独立于编程语言(但各语言实现可能有细微差异)。

  • 通过模式(pattern)匹配文本,而非直接比较字符串。

2 正则表达式用途

正则表达式的主要应用场景包括:

用途说明示例
文本搜索快速查找符合特定规则的字符串(如邮箱、电话号码)。在日志中查找所有错误代码 ERROR:\d+
数据验证验证用户输入格式(如密码强度、邮箱合法性)。检查密码是否包含大小写和数字 ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,}$
文本替换批量替换符合规则的文本(如敏感词过滤、格式调整)。将日期格式从 MM/DD/YYYY 替换为 YYYY-MM-DD
字符串提取从复杂文本中提取特定部分(如网页中的URL、文件中的关键词)。提取HTML中的链接 href="(.*?)"
文本分割按规则拆分字符串(如CSV文件按分隔符分列)。按逗号或分号分割 [,;]
日志分析解析结构化日志数据(如提取时间戳、IP地址)。匹配IP地址 \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b
代码处理在IDE或编辑器中批量重构代码(如重命名变量、调整格式)。替换所有 var 为 let

关键记忆点:

  • 定义:用模式描述字符串规则的文本工具。

  • 用途:搜索、验证、替换、提取、分割文本。

  • 核心价值:高效处理复杂的字符串操作,减少手动编码。

二 正则表达式类型

1 基础正则表达式示例

语法说明示例
查找特定字符直接匹配指定的字符或字符串。"hello" 匹配文本中的 hello
中括号 []匹配括号内的任意一个字符(字符集合)。[aeiou] 匹配任意一个元音字母。
行首 ^ 和行尾 $^ 匹配行首,$ 匹配行尾。^Hello 匹配以 Hello 开头的行。
任意字符 . 和重复字符 *. 匹配任意单个字符(除换行符),* 匹配前一个字符 0 次或多次h.*o 匹配 hellohalo 等。
连续字符范围 {}{n} 匹配前一个字符 n 次{n,m} 匹配 n 到 m 次a{2,4} 匹配 aaaaaaaaa

以下是正则表达式的语法:

(1)查找特定字符

语法:

grep  -n  [ 参数 ]  文本             //查找文本行号

grep  -nv  [ 参数 ]   文本            //查找文本行号相反的参数

语法示例:

(2)利用中括号” [] “来查找集合字符

范围表示法:

  • [a-z]:匹配任意小写字母。

  • [A-Z]:匹配任意大写字母。

  • [0-9]:匹配任意数字。

  • 组合范围[a-zA-Z0-9] 匹配所有字母和数字。

特殊字符转义:

  • 在 [] 内,大多数特殊字符(如 .*)会失去特殊含义,无需转义。

  • 但以下字符需注意:

    • ^:仅在开头表示排除,其他位置作为普通字符。

    • -:表示范围时(如 a-z),需放在开头或结尾避免歧义。

    • ]:需用 \] 转义或放在开头。

语法示例:

(3)查找行首字符” ^ “与行尾字符”$“

语法:

行首字符” ^ “

  • ^ 匹配一行的开头位置(在行首之前的位置)。

  • 通常用于确保模式出现在行首。

行尾字符”$“

  • $ 匹配一行的结尾位置(在行末换行符之前的位置)。

  • 通常用于确保模式出现在行尾。

语法示例:

grep '^hello' file.txt    # 查找以 "hello" 开头的行

grep -v '^#' file.txt    # 查找不以 `#` 开头的行(常用于过滤注释行)

grep 'world$' file.txt    # 查找以 "world" 结尾的行

grep '^[A-Z]' file.txt    # 查找以大写字母开头的行
grep '[0-9]$' file.txt    # 查找以数字结尾的行

(4)查找任意一个字符” .“ 与重复字符”*“

在正则表达式中,.(点)和 *(星号)是两个核心元字符,分别用于匹配任意单个字符重复前一个字符/模式

语法示例:

grep  -n  'w..d'   test.txt

grep  -n  'ooo*'   test.txt

grep  -n  'woo*d'   test.txt

(5)查找连续字符范围”{}“

在正则表达式中,大括号 {} 用于指定 前一个字符或模式的重复次数,是精确控制匹配数量的重要工具。

语法示例:

# grep (BRE):需转义
echo "aaa" | grep 'a\{2\}'

# grep (ERE):免转义
echo "aaa" | grep -E 'a{2}'

# sed (BRE):需转义
echo "aaa" | sed -n '/a\{2\}/p'

# sed (ERE):免转义
echo "aaa" | sed -E -n '/a{2}/p'

2 元字符总结

元字符含义
.匹配任意单个字符(除换行符 \n)。
^匹配行首(在 [] 内表示取反,如 [^a] 匹配非 a 的字符)。
$匹配行尾。
*匹配前一个字符 0 次或多次(贪婪匹配)。
+匹配前一个字符 1 次或多次(需在扩展正则中使用)。
?匹配前一个字符 0 次或 1 次(也可用于非贪婪匹配,如 .*?)。
{n}匹配前一个字符 恰好 n 次
{n,}匹配前一个字符 至少 n 次
{n,m}匹配前一个字符 n 到 m 次
[]匹配括号内的任意一个字符,如 [a-z] 匹配任意小写字母。
|

 匹配(需在扩展正则中使用),如 `cat

dog匹配catdog`。

()分组匹配,可用于提取或应用量词,如 (ab)+ 匹配 ababab 等。
\转义字符,用于匹配特殊字符本身,如 \. 匹配 .\* 匹配 *

3 扩展正则表达式

扩展正则表达式在基础正则(BRE)上增加了更强大的功能,通常需要加 -E 选项(如 grep -E 或 egrep)。

扩展功能说明示例
+匹配前一个字符 1 次或多次(BRE 中需用 \{1,\})。go+l 匹配 golgooool
?匹配前一个字符 0 次或 1 次(BRE 中需用 \{0,1\})。colou?r 匹配 color 或 colour
|` 匹配,可组合多个模式。`cat dog匹配catdog`。
()分组匹配,支持捕获组和反向引用。(ab)+ 匹配 ababab 等。
\d\w\s预定义字符类(部分工具支持):
\d 数字,\w 单词字符,\s 空白符。
\d{3} 匹配 123456 等。

4 扩展正则表达式和基础正则表达式的对比总结

特性基础正则表达式(BRE)扩展正则表达式(ERE)说明
量词*\{n,m\}*+?{n,m}ERE 支持更简洁的量词写法,BRE 需转义 {}
或匹配 |不支持(需 | 转义)支持ERE 可直接使用 | 表示“或”关系,BRE 需 `\
分组 ()\( \)(需转义)()(直接使用)ERE 分组无需转义,BRE 需写成 \(...\)
行首/行尾^$^$两者相同。
字符集 []支持支持两者相同。
非贪婪匹配不支持(默认贪婪)支持 *?+?ERE 可用 ? 实现非贪婪匹配,BRE 无此功能。
预定义字符类部分支持(如 \w 依赖工具)更广泛支持(如 \d\sERE 在某些工具(如 grep -P)支持 Perl 风格正则。
适用工具grepsed(默认)grep -EegrepawkPerlPythonERE 更现代,BRE 主要用于传统 Unix 工具。

关键区别:

  1. 语法简洁性

    • ERE 的 +?|() 等无需转义,BRE 需用 \+\?\|\(\)

    • 例如匹配 color 或 colour

      • BRE: colou\?r

      • ERE: colou?r

  2. 功能扩展性

    • ERE 支持非贪婪匹配.*?)、或运算|)、更灵活的量词,BRE 功能受限。

  3. 工具兼容性

    • BRE 是传统 Unix 工具(如 grepsed)的默认模式,ERE 需通过 -E 选项或 egrep 启用。

    • 现代语言(如 Python、Perl)默认使用 ERE 或更强大的正则引擎(PCRE)。

如何选择?

  • 使用 BRE:兼容老旧脚本或必须使用 sed/grep 默认模式时。

  • 使用 ERE:需要更简洁的语法和高级功能(如 |+)时,优先选择 grep -E 或 awk

一句话总结ERE 是 BRE 的增强版,语法更简洁、功能更强大,但需注意工具兼容性。

三 文本处理器

1 sed工具

sed(Stream Editor)是一个强大的流式文本编辑器,主要用于对文本进行查找、替换、删除、插入等操作,支持正则表达式,适合批量处理文本。

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

  1. 读取:将 "hello world" 读入模式空间。

  2. 执行:依次执行替换命令 → "Hi world" → "Hi universe"

  3. 显示:输出最终结果 "Hi universe"

sed语法:

sed  [ 选项 ]  “操作”  参数

sed  [ 选项 ]  -f  scriptfile   参数

常见的sed命令选项主要包含以下几种:

选项作用
-e (编辑脚本)指定要执行的编辑命令(可多次使用,连接多个命令)
-f (从文件读取脚本)表使用指定的脚本文件来处理输入的文本文件
-h 或 --help显示帮助
-n (静默模式)表示仅显示处理后的结果
-i (直接修改文件)直接编辑源文件(谨慎使用,建议先备份或测试)
-r (扩展正则表达式)启用扩展正则表达式
-l (行缓冲输出)指定输出行的长度(通常用于特殊设备或格式化)

(1)输出符合条件的文本(p表示正常输出)

在正则表达式和文本处理工具(如 grepsedawk)中,p 命令 或 print 动作 用于 显式输出符合条件的文本,通常与条件匹配结合使用。

语法示例:

grep 'pattern' file.txt      # 输出包含 'pattern' 的整行

grep -o 'pattern' file.txt   # 仅输出匹配 'pattern' 的部分

grep -Po 'pattern' file.txt  # 支持 Perl 兼容正则(如非贪婪匹配 `.*?`)

sed -n '/pattern/p' file.txt  # 仅输出匹配 'pattern' 的行(`-n` 抑制默认输出)

(2)删除符合条件的文本(d)

在文本处理工具(如 sedawkgrep)中,d 命令 或 delete 动作 用于 删除符合条件的文本行

语法示例:

sed '/pattern/d' file.txt      # 删除匹配 `pattern` 的行

sed '1,3d' file.txt           # 删除第1~3行
sed '$d' file.txt             # 删除最后一行

sed '/pattern/!d' file.txt    # 删除不匹配 `pattern` 的行(即保留匹配行)

sed -i '/error/d' log.txt     # 直接删除文件中的错误行(原文件被修改)

awk '!/pattern/' file.txt     # 删除匹配 `pattern` 的行(`!` 表示否定)
awk 'NR>3' file.txt          # 删除前3行(保留行号大于3的行)

(3)替换符合条件的文本

在文本处理中,替换符合条件的文本是核心操作之一,主要通过 sedawkgrep(结合其他工具)等实现。

语法示例:

sed 's/原内容/替换内容/[flags]' file.txt

  • s:替换命令

  • flags 常用选项:

    • g:全局替换(一行中所有匹配)。

    • i:忽略大小写(如 s/pattern/replace/i)。

    • p:打印替换成功的行(需与 -n 配合)。

echo "hello world" | sed 's/world/China/'      # 输出:hello China
echo "a b a" | sed 's/a/A/g'                  # 全局替换:A b A
sed -i 's/foo/bar/g' file.txt                 # 直接修改文件

sed '2s/old/new/' file.txt       # 仅替换第2行的内容

echo "2023-10-01" | sed 's/\([0-9]\{4\}\)-\([0-9]\{2\}\)/\2\/\1/'
# 输出:10/2023-01(分组重组)

sed '/error/s/foo/bar/' file.txt  # 仅在含 "error" 的行替换

(4)迁移符合条件的文本

作用:在指定位置插入、追加、替换或读取外部文件内容。

命令说明示例
i在匹配行前插入sed '/pattern/i\new line' file
a在匹配行后追加sed '/pattern/a\new line' file
c替换匹配行sed '/pattern/c\replacement' file
r读取文件并插入sed '/pattern/r otherfile' file
w将匹配行写入文件sed '/pattern/w output.txt' file

语法示例:

(5)使用脚本编辑文件

以下是关于 使用脚本编辑文件 的全面总结,涵盖常用工具(sedawkperl 等)、核心操作(替换、删除、插入)

语法示例:

sed -i 's/old/new/g' file.txt          # 全局替换
sed '/pattern/s/old/new/' file.txt     # 仅替换匹配行

awk '{gsub(/old/, "new"); print}' file.txt > tmp && mv tmp file.txt

perl -pi -e 's/old/new/g' file.txt     # 直接修改文件

(6)sed直接操作文件示例

#!/bin/bash
#指定样本文件路径,配置文件路径
SAMPLE="/usr/share/doc/vsftpd-3.0.2/EXAMPLE/INTERNET_SITE/vsftpd.conf"
CONFIG="/etc/vsftpd/vsftpd.conf"
#备份原来的配置文件,检测文件名为/etc/vsftpd/vsftpd.conf.bak备份文件是否存在,若不存在则使用cp命令进行文件备份
[ ! -e "$CONFIG.bak" ]&& cp $CONFIG $CONFIG.bak
#基于样本配置进行调整,覆盖现有文件

2 awk工具

awk 是一种强大的文本处理工具,擅长按行和列处理结构化数据(如日志、CSV 文件),支持变量、条件判断、循环等编程特性。

awk常用变量:

变量含义示例
NR当前行号awk 'NR==1 {print}'(输出第 1 行)
NF当前行的列数awk '{print NF}'(输出每行列数)
FS输入字段分隔符(默认空格)awk -F':' '{print $1}'
OFS输出字段分隔符(默认空格)awk 'BEGIN {OFS="-"}{print $1,$2}'
FILENAME当前文件名awk '{print FILENAME}'

awk语法:

awk [选项] '模式 {动作}' 文件名

  • 选项awk 支持一些选项,如 -F 用于指定字段分隔符。
  • 模式:用于匹配输入行的条件,可以是正则表达式、比较表达式等。如果省略模式,则默认匹配所有行。
  • 动作:在匹配到的行上执行的操作,通常是一系列的 awk 语句,用花括号 {} 括起来。
  • 文件名:要处理的输入文件。如果省略文件名,则从标准输入读取数据。

(1)按行输出文本

语法示例:

若要输出一个文件的所有行,可使用 print 语句,它会默认输出当前行。示例命令如下:

awk '{print}' filename.txt

在这个命令里,{print} 是 awk 的动作部分,print 函数会打印当前处理的行。filename.txt 是你要处理的文件名。若要从标准输入读取内容,可省略文件名,直接输入文本并按 Ctrl + D 结束输入。

awk '/^hello/ {print}' filename.txt

(2)按字段输出文本

awk默认以空格或制表符作为字段分隔符,使用$n来表示第n个字段(n是从 1 开始的正整数),$0表示整行内容。

语法示例:

awk '{print $1}' data.txt         //输出每行的第一个字段

awk '{print $1, $3}' data.txt                //输出每行的第一个和第三个字段

awk -F ',' '{print $2}' info.csv                //以逗号作为分隔符,输出每行的第二个字段

awk -F ',' 'NR > 1 {printf "%-10s %d\n", $2, $3}' info.csv

//以固定宽度输出名字和年龄

(3)通过管道,双引号调用shell命令

awk流量控制:

语法示例说明
BEGIN{}awk 'BEGIN {print "Start"}{print}'处理前执行
END{}awk '{sum+=$1} END {print sum}'处理后执行
if 条件awk '{if($1>10) print $0}'条件判断
for 循环awk '{for(i=1;i<=NF;i++) print $i}'遍历列

语法:

{

        # 要执行的 awk 操作

         command = "shell 命令"

        print $1 | command

        close(command)

}

这里的 print $1 是把 $1 字段的内容通过管道传递给 command 所代表的 shell 命令。使用完管道后,需要用 close(command) 来关闭它,防止出现文件描述符泄漏的问题。

3 sed工具和awk工具的对比总结

sed 和 awk 是 Linux/Unix 中两大经典文本处理工具,虽然功能有部分重叠,但设计目标和适用场景差异显著。以下是它们的对比总结:

设计定位:

工具核心定位适用场景
sed流编辑器(Stream Editor)以行为单位的文本替换、删除、插入等简单编辑操作。
awk模式扫描与处理语言(AWK Language)基于列/字段的复杂数据处理、计算、报表生成等。

核心功能对比:

特性sedawk
处理单位按行处理(默认操作单位是整行)按行处理,但可拆分字段(默认以空格/制表符分列)
编程能力支持简单命令,无变量和算术运算支持变量、数组、循环、条件判断、函数等完整编程特性
文本替换强项(s/old/new/ 语法高效)支持替换,但语法不如 sed 简洁
字段处理弱(需依赖正则表达式截取字段)强(直接通过 $1$2 访问列)
输出控制简单输出或静默模式(-n + p灵活格式化输出(printfprint
多行处理有限(需借助保持空间/模式空间技巧)更灵活(可通过变量缓存多行数据)

如何选用:

  • 用 sed 如果

    • 只需简单的行级编辑(如替换、删除)。

    • 处理大文件时追求更高性能

  • 用 awk 如果

    • 需要按列处理数据数学计算

    • 任务涉及条件判断、循环或复杂逻辑

相关文章:

  • Tomcat大版本升级教程
  • B端可视化方案,如何助力企业精准决策,抢占市场先机
  • MyBatis与MyBatis-Plus:字段自动填充的两种实现方式
  • 【Netty篇】Future Promise 详解
  • 【物联网】基于LORA组网的远程环境监测系统设计
  • 医疗大模型落地方案:技术选型、部署策略与调优
  • 与/或形演绎推理——基于王永庆著《人工智能原理与方法》的深度解析
  • GitHub 趋势日报 (2025年04月15日)
  • OpenCV操作函数
  • kafka服务端和springboot中使用
  • Excel数据自动填充到Word自定义表格
  • OpenCV day4
  • ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(输入类外设之按键Button)
  • Spark-SQL核心编程3
  • Python爬虫第15节-2025今日头条街拍美图抓取实战
  • jupyter 文件浏览器,加强版,超好用,免费exe
  • 工业数据治理范式革新:时序数据库 TDengine虚拟表技术解析
  • 【Web APIs】JavaScript 操作多个元素 ③ ( 鼠标经过高亮显示 | onmouseover 事件设置 | onmouseout 事件设置 )
  • docker 安装TDengine 时序数据库
  • ARINC818协议(二)
  • 小说网站个人可以做吗/cps推广
  • 做seo是什么意思/苏州排名搜索优化
  • 吉林省人民政府电话/seo网络推广报价
  • 苏州做企业网站公司/seo的方式有哪些
  • 怎么给幼儿园做网站/北京搜索优化推广公司
  • 惠阳东莞网站建设/互联网推广引流