文章目录
- 前言
- 一、什么是sed
- 二、sed的原理
- 2.1 sed工作流程的三个步骤
- 2.2 sed的两个重要空间:
- 2.3 sed的具体运作流程
- 三、sed的常见用法
- 3.1 sed的基本格式
- 3.2 常用选项
- 3.3 常用操作
- 3.3.1 基本语法规则
- 3.3.2 常用操作命令
- 3.4 操作用法示例
- 3.4.1 输出符合条件的文本(`p` 正常输出)
- 3.4.2 结合正则表达式进行输出
- 3.4.3 删除符合条件的文本`d`
- 3.4.4 替换符合条件的文本`tr`
- 3.4.5 迁移符合条件的文本
- 3.4.6 使用脚本编辑文件
- 四、生产环境的sed使用
- 4.1 修改ip/监听地址
- 4.2 编写vsftpd服务的自动配置
- 总结
前言
想象一下,你正在整理一堆杂乱的文件,手忙脚乱地复制、粘贴、删除某些内容,甚至还要批量替换某些词。如果手动操作,不仅容易出错,还特别浪费时间。这时候,sed就像一位低调但高效的文本编辑助手,帮你自动完成这些繁琐的任务。
它不会像图形化工具那样花哨,但只要你告诉它规则,比如“把所有的‘苹果’换成‘橙子’”或者“删除空行”,它就能眨眼间搞定。它的风格简洁直接,擅长处理一行一行的文本,就像流水线上的工人,精准又高效。
不过,如果你觉得sed只能做简单的“查找替换”,那就太小看它了——它还能匹配模式、条件编辑,甚至结合正则表达式玩出更复杂的操作。而当你熟悉了sed之后,可能会发现,有时候你需要的不只是编辑文本,还要分析、计算、提取数据……这时候,另一位更强大的搭档awk就该登场了。
但别急,先让我们把sed的基本功练扎实,毕竟再厉害的编程技巧,也得从最顺手的小工具开始。
一、什么是sed
sed(Stream EDitor,流编辑器)是一个强大而轻量的流式文本编辑器。它诞生于 Unix 早期,由 Lee E. McMahon 于 1973 年到 1974 年间开发,是 Linux/Unix 系统中最基础和最重要的工具之一。
它的核心特点如下:
- 非交互式:与
vim
或nano
这类交互式编辑器不同,sed
通过接收命令或脚本文件来批量处理文本,无需用户介入。这使得它非常适合在脚本和自动化任务中使用。 - 面向数据流:
sed
逐行处理输入(可以是文件或标准输入),将结果输出到标准输出。它不会直接修改原始文件(除非明确指定),这保证了操作的安全性。 - 功能强大:主要功能包括文本替换、删除、打印、插入、追加、模式匹配等,尤其擅长查找和替换。
- 基于正则表达式:其强大的模式匹配能力建立在正则表达式之上,可以非常灵活地定位文本。
简单来说,sed
就像一个预设了规则的过滤器和加工器,文本流经过它,会被自动地按照指令进行修改和整理。
二、sed的原理
2.1 sed工作流程的三个步骤
理解 sed
的原理是掌握它的关键。其工作流程可以概括为以下三个步骤:
-
读取(Read):
sed
从输入流(文件或管道)中一次读取一行内容。- 将这行内容存储在其内部的临时缓冲区中,这个缓冲区称为模式空间(Pattern Space)。
-
执行(Execute):
- 将用户提供的所有
sed
命令(或脚本中的命令)按顺序应用到模式空间中的内容上。 - 这是核心步骤,所有的替换、删除、打印等操作都在这里发生。
- 将用户提供的所有
-
输出(Print):
- 执行完所有命令后,除非有特殊指令(如
d
删除命令),否则模式空间中当前的内容会被自动输出到标准输出(屏幕)。 - 然后清空模式空间,接着读取下一行,重复上述过程,直到处理完所有输入行。
- 执行完所有命令后,除非有特殊指令(如
这种 “读取-执行-输出” 的流水线模式,使得
sed
在处理超大文件时效率极高,因为它永远不会将整个文件加载到内存中。
2.2 sed的两个重要空间:
- 模式空间(Pattern Space):如上所述,这是当前处理行的“工作台”,大部分操作都在这里进行。
- 保持空间(Hold Space):一个辅助的缓冲区,用作临时存储。模式空间的内容可以和保持空间进行交换(
g
、h
)、追加(G
)等操作,用于实现更复杂的多行处理功能。
2.3 sed的具体运作流程
- 将一行的内容读入模式空间。
- 从指定的操作指令中取出第一条指令,判断是否匹配pattern。
- 如果不匹配,直接不执行匹配条件后的编辑命令,转而读取下一条指令;如果匹配则执行编辑命令,对模式空间内的内容进行编辑,然后读取下一条指令。
- 当所有指令执行完毕,默认会输出模式空间内的内容,然后清空模式空间,读取下一行的内容。
- 当完成对所有行的读取时,结束。
注意:默认情况下所有的 sed 命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出(
-i
)。
三、sed的常见用法
3.1 sed的基本格式
调用sed命令有两种基本格式:
# 一、直接输入操作
sed [选项] '操作' 参数
# 二、通过调用脚本进行操作
sed [选项] -f scriptfile 参数
其中,“参数”指操作的目标文件,多个文件时用逗号分隔;“scriptfile”为脚本文件,需用 -f
指定。
3.2 常用选项
以下是 sed
常用选项的表格整理:
短选项 | 长选项 | 功能描述 |
---|---|---|
-e | --expression= | 用指定命令或脚本处理输入文件,可多次使用以叠加修改 |
-f | --file= | 用指定脚本文件中的命令处理输入文件 |
-h | --help | 显示帮助信息并退出 |
-n | --quiet /silent | 仅显示被脚本处理后的行(默认输出所有行) |
-i.bak | - | 直接修改原文件(.bak 为备份扩展名,可省略则仅修改不备份) |
-r /-E | - | 使用扩展正则表达式(-r 为GNU扩展,-E 符合POSIX) |
-s | - | 将多个输入文件视为独立文件,而非连续流(默认合并处理) |
注:
-i
和-i.bak
实际行为相同,差异在于是否保留备份文件(如-i
直接覆盖,-i.bak
保留原文件备份)。- 部分选项(如
-r
/-E
)在不同系统实现中可能存在别名差异。
3.3 常用操作
3.3.1 基本语法规则
[n1[,n2]]
格式用于指定行范围,其中 n1
和 n2
均为行号。
- 单行操作:
n1
表示仅对第n1
行生效。 - 范围操作:
n1,n2
表示对第n1
行至第n2
行生效。 - 省略
n1
:如,n2
表示从第1行至第n2
行。 - 省略
n2
:如n1,
表示从第n1
行至文件末尾。
3.3.2 常用操作命令
-
a
:追加内容
在指定行下方追加新行。
示例:5a
在第5行下方追加,输入内容后以.
结束。 -
c
:替换行
将选定行替换为新内容。
示例:5,10c
替换第5-10行,输入新内容后以.
结束。 -
d
:删除行
删除选定行。
示例:5,20d
删除第5-20行。 -
i
:插入行
在选定行上方插入新内容。
示例:5i
在第5行上方插入,输入内容后以.
结束。 -
p
:打印内容
显示选定行内容,常与-n
参数联用显示行号。
示例:5,20p
打印第5-20行。 -
s
:替换文本
对选定行执行文本替换,语法为s/原内容/新内容/[g]
。g
为全局替换标志(可选)。
示例:5,10s/foo/bar/g
将第5-10行的foo
替换为bar
。
-
y
:字符转换
按字符一一映射转换,语法为y/原字符集/新字符集/
。
示例:5,20y/abc/ABC/
将第5-20行的a→A
、b→B
、c→C
。
3.4 操作用法示例
3.4.1 输出符合条件的文本(p
正常输出)
sed -n 'p' test.txt # 输出所有内容,等同于 cat
sed -n '3p' test.txt # 输出第3行
sed -n '3,5p' test.txt # 输出3~5行
sed -n 'p;n' test.txt # 输出所有奇数行
sed -n 'n;p' test.txt # 输出所有偶数行
sed -n '1,5{p;n}' test.txt # 输出1~5行之间的奇数行
sed -n '10,${n;p}' test.txt # 输出第10行至文件尾的偶数行
sed -n 'h;n;p;g;p' test.txt #输出所有内容,但两行间的内容互换,h,复制到保存空间,g,从保存空间获取到模式空间
3.4.2 结合正则表达式进行输出
sed -n '/the/p' test.txt # 输出包含 the 的行
sed -n '4,/the/p' test.txt # 输出从第4行至第一个包含 the 的行
sed -n '/the/=' test.txt # 输出包含 the 的行号
sed -n '/^PI/p' test.txt # 输出以 PI 开头的行
sed -n '/[0-9]$/p' test.txt # 输出以数字结尾的行
sed -n '/\<woood\>/p' test.txt # 输出包含单词 wood 的行,'\< \>'是边界,被包含的内容会被精确匹配
3.4.3 删除符合条件的文本d
nl test.txt | sed '3d' # 删除第3行
nl test.txt | sed '3,5d' # 删除3~5行
nl test.txt | sed '/cross/d' # 删除包含 cross 的行
sed '/^[a-z]/d' test.txt # 删除以小写字母开头的行
sed '/\.$/d' test.txt # 删除以“.”结尾的行
sed '/^$/d' test.txt # 删除所有空行# 删除连续空行(只保留一个)可使用:cat -s test.txt
3.4.4 替换符合条件的文本tr
sed 's/the/THE/' test.txt # 每行第一个 the 替换为 THE
sed 's/l/L/2' test.txt # 每行第二个 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
# 直接修改配置文件示例:
sed -i.bak 's/SELINUX=disabled/SELINUX=enable/' /etc/selinux/config
3.4.5 迁移符合条件的文本
-
H:复制到剪贴板;
-
g、G:将剪贴板中的数据覆盖/追加至指定行;
-
w:保存为文件;
-
r:读取指定文件;
-
a:追加指定内容。具体操作方法如下所示。
-
I,i 忽略大小写
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 的行另存为文件
sed '/the/r /etc/hostname' test.txt # 在包含 the 的每行后添加文件内容
sed '3aNew' test.txt # 在第3行后插入新行,内容为 New
sed '/the/aNew' test.txt # 在包含 the 的每行后插入新行
sed '3aNew1\nNew2' test.txt # 在第3行后插入多行内容
sed '/the/IaNew' test.txt # I,i 可用于忽略大小写
3.4.6 使用脚本编辑文件
sed '1,5{H;d};16G'
以上命令可以转换成脚本文件,将多个编辑指令存入脚本文件(每行一条),通过 -f
调用:
# 编辑脚本文件:
vi opt.list
内容如下:
1,5H
1,5d
16G# 使用脚本:
sed -f opt.list test.txt
||
表示上一条命令执行失败后才执行下一条。
四、生产环境的sed使用
4.1 修改ip/监听地址
需求: 需要将ens33网络接口的IP地址修改为 192.168.10.100
sed -i 's/^IPADDR=.*/IPADDR=192.168.10.100/' /etc/sysconfig/network_scripts/ifcfg-ens33
需求: 需要将 Apache 的监听地址修改为 192.168.10.100,端口修改为 8080
# 修改监听地址
sudo sed -i 's/^Listen .*/Listen 192.168.10.100:8080/'
/etc/httpd/conf/httpd.conf# 修改 ServerName
sed -i 's/^ServerName .*/ServerName 192.168.10.100:8080/'
/etc/httpd/conf/httpd.conf
4.2 编写vsftpd服务的自动配置
需求: 编写一个脚本,用来调整 vsftpd 服务配置,要求禁止匿名用户,但允许本地用户(也允许写入)。
#!/bin/bash
SAMPLE="/usr/share/doc/vsftpd-3.0.2/EXAMPLE/INTERNET_SITE/vsftpd.conf"
#系统自带的变量路径
CONFIG="/etc/vsftpd/vsftpd.conf"# 备份原配置文件
[ ! -e "$CONFIG.bak" ] && cp $CONFIG $CONFIG.bak# 调整配置
sed -e '/^anonymous_enable/s/YES/NO/g' $SAMPLE > $CONFIG
sed -i -e '/^local_enable/s/NO/YES/g' -e '/^write_enable/s/NO/YES/g' $CONFIG
grep "listen" $CONFIG || sed -i '$alisten=YES' $CONFIG# 重启并设置开机自启
systemctl restart vsftpd
systemctl enable vsftpd
总结
别停下,你已手握文本处理的利刃!
sed 看似简单,却是自动化脚本的灵魂。每一次精准的替换、每一次高效的删除,都在为你节省宝贵的时间。
记住:高手不是一天练成的,而是在一次次“查找-替换”中磨出来的。
你已经掌握了原理,接下来就是大胆实践:
- 去清理日志、去修改配置、去批量重命名……
- 让 sed 成为你的得力助手,把重复劳动交给机器!
未来的你,会感谢现在努力学习的自己。继续征服命令行,下一站:awk! 🚀