Shell 秘典(卷七)—— 流刃裁文秘术・sed 玄章精解
文章目录
- 前言
- 一、sed 工具基础认知
- 1.1 sed 工具的定义与核心作用
- 1.2 sed 工具的工作流程
- 二、sed 命令的常见用法
- 2.1 sed 命令的基本格式
- 2.2 sed 命令的常用选项
- 2.3 sed 命令的操作类型
- 三、sed 工具的用法示例
- 3.1 输出符合条件的文本(p 操作)
- 3.2 结合正则表达式输出
- 3.3 删除符合条件的文本(d 操作)
- 3.4 替换符合条件的文本
- 3.5 迁移符合条件的文本
- 3.6 使用脚本编辑文件
- 3.7 分组操作
- 四、实战案例
- 总结
前言
Linux/UNIX 之境,如浩渺修真界,系统日志为 “天机卷宗”,配置文件为 “宗门法典”,数据洪流为 “灵脉浊流”。修士欲掌此界,需习得 “裁文断字、理脉清浊” 之能 —— 而 sed
(Stream EDitor),正是此道中的 “流刃” 至宝,乃 Shell 三剑客之一,专司文本流之雕琢,为运维修士、编程道人必备之术。
此 “流刃” 之妙,在 “随流而斩、不损本源”:凡经其处理之文本,默认不扰源文件根基,如修士以灵力隔空御刃,裁删修改皆在 “流” 中完成,不伤原始卷宗;更兼可融 “正则灵韵”(正则表达式),能辨复杂文式、精准定位,如刃附灵纹,可破千变万化的文本迷阵。
本卷为 “流刃裁文秘术” 专章,将系统性拆解 sed
之玄奥:从 “流刃运转心法”(工作流程)、“刃法基础符印”(核心语法),到 “实战斩文之术”(文本输出、删除、替换、迁移),每一招皆附实例印证。无论初入此界的筑基修士(Linux 初学者),还是已掌根基的金丹道人(资深管理员),皆可借本卷悟透 sed
之刃的用法,让日志析秘、配置修编、数据提纯之事,从 “耗时费力” 化为 “刃到功成”,大幅精进自动化脚本(术法)之能。
今邀诸位执此 “流刃”,共探文本处理之秘境,解锁 Linux 修真界的裁文新道!
一、sed 工具基础认知
1.1 sed 工具的定义与核心作用
sed(Stream EDitor)是一款高效易用的文本处理工具。它以逐行方式读取文本,根据用户定义的规则执行查找替换、删除、插入等编辑操作,并输出处理结果。
作为非交互式文本处理器,sed特别适合集成到Shell脚本中实现自动化文本处理任务。
1.2 sed 工具的工作流程
sed 的工作流程主要包括以下三个步骤:
- 读取:从输入流(文件、管道或标准输入)中读取一行内容,存入临时的缓冲区中,又称之模式空间(pattern space)。
- 执行:默认情况下,所有 sed 命令按顺序在模式空间中执行,除非指定了行地址。
- 显示:将处理后的内容发送到输出流,随后清空模式空间。
该过程会重复执行,直到所有内容处理完毕。
注意:默认情况下,sed 不会修改原始文件,除非使用重定向存储输出。
二、sed 命令的常见用法
2.1 sed 命令的基本格式
sed 命令有两种常用调用格式:
sed [选项] '操作' 参数
sed [选项] -f scriptfile 参数
其中,参数
表示目标文件,多个文件时用逗号分隔;scriptfile
是脚本文件,需使用 -f
选项指定。
当脚本文件出现在目标文件之前时,表示通过指定的脚本文件来处理输入的目标文件。
2.2 sed 命令的常用选项
-e
或--expression=
:指定命令或脚本处理输入的文本文件-f
或--file=
:指定脚本文件处理文本-h
或--help
:显示帮助信息-n
、--quiet
或silent
:仅显示处理后的结果,取消默认输出-i.bak
:直接编辑文件,并备份原文件-r
、-E
:使用扩展正则表达式-s
:将多个文件视为独立文件,而非连续流
2.3 sed 命令的操作类型
“操作”用于指定对文件操作的动作行为,也就是 sed 的命令。操作符通常格式为 [n1[,n2]]动作
,其中 n1
、n2
为可选行号。常见操作包括:
a
:在当期行下方添加一行c
:替换选定行d
:删除选定行i
:在选定行上方插入一行p
:打印内容,常与-n
联用s
:替换指定字符y
:字符转换n
:读取下一行到模式空间(跳过当前行)。g
:全局替换(每行所有匹配项)
三、sed 工具的用法示例
以下示例使用 test.txt
文件进行演示。
vim test.txthe was short and fat.
He was wearing a blue polo shirt with black pants.
The home of Football on BBC Sport online.
the tongue is boneless but it breaks bones.12!
google is the best tools for search keyword.
The year ahead will test our political establishment to the limit.
PI=3.141592653589793238462643383249901429
a wood cross!
Actions speak louder than words#woood #
#woooooood # AxyzxyzxyzxyzC
I bet this place is really spooky late at night!
Misfortunes never come alone/single.
I shouldn't have lett so tast.
3.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 '10,${n;p}' test.txt
命令时,读取流程如下:
- 从文件的第10行开始处理
- 每次读取两行:
- 第1次读取:跳过第10行,打印第11行
- 第2次读取:跳过第12行,打印第13行
- 以此类推
- 最终输出结果是文件的第11、13、15等奇数行(相对于起始行号),直到文件结束,包含空行在内都会被输出
案例:
ifconfig ens33 | sed -n 2p # 直接显示第二行内容
3.2 结合正则表达式输出
sed
命令结合正则表达式时,格式略有不同,正则表达式以/
包围。例如,以下示例展示了sed
与正则表达式的结合用法:
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 '/\<wood\>/p' test.txt # 精准匹配单词 "wood" 的行
3.3 删除符合条件的文本(d 操作)
由于后续示例仍需使用测试文件 test.txt,建议在执行删除操作前先备份该文件。以下示例展示了sed
命令的几种常见删除用法。
为更直观地查看命令执行效果,下面的示例中使用了nl
命令来统计文件行数。
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 替换符合条件的文本
在使用 sed 命令进行替换操作时需要用到 s
(字符串替换)、c
(整行/整块替换)、y
(字符转换)命令选项,常见的用法如下所示。
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"
实际应用:
# 将/etc/selinux/config文件中的SELINUX=disabled修改为SELINUX=enable,并且备份原文件
sed -i.bak 's/SELINUX=disabled/SELINUX=enable/' /etc/selinux/config
3.5 迁移符合条件的文本
在使用 sed 命令迁移符合条件的文本时,常用的参数包括:
- H:将内容复制到剪贴板
- g/G:将剪贴板数据覆盖/追加到指定行
- w:将内容保存为文件
- r:读取指定文件内容
- a:在指定位置追加内容
- I/i:执行忽略大小写的匹配操作
sed '/the/{H;d};$G' test.txt # 将包含 "the" 的行移至文件末尾
sed '1,5{H;d};15G' test.txt # 将第 1-5 行内容移至第 15 行后
sed '/the/w out.file' test.txt # 将包含 "the" 的行另存为文件out.file
sed '/the/r /etc/hostname' test.txt # 在包含 "the" 的行后插入/etc/hostname文件内容
sed '3aNew' test.txt # 在第 3 行后插入新行
sed '/the/aNew' test.txt # 在包含 "the" 的行后插入新行
sed '3aNew1\nNew2' test.txt # 在第 3 行后插入多行内容,中间的\n 表示换行
3.6 使用脚本编辑文件
使用 sed 脚本将多个编辑指令存放到文件中(每行一条编辑指令),通过-f
选项来调用。例如执行以下命令即可将第 1~5 行内容转移至第 16 行后。
sed '1,5{H;d};16G' test.txt #将第 1~5 行内容转移至第 16 行后
创建一个脚本文件 opt.list
,内容如下:
vi opt.list1,5H
1,5d
16G
然后执行脚本:
sed -f opt.list test.txt
3.7 分组操作
当我们需要对一行数据进行多次操作的时候我们可以使用{}
进行分组。
# 在/tmp/passwd文件中查找包含"root"的行,将这些行的"root"替换为"ROOT",并同时将所有小写字母"x"替换为大写"X"。
sed '/root/{s/root/ROOT/;s/x/X/g}' /tmp/passwd
# 将/tmp/passwd文件中1-10行打印出来,并在所有行中查找包含root的行,将其中的root替换为ROOT,同时将所有x替换为X。
sed -ne '/root/{s/root/ROOT/;s/x/X/g}' -ne '1,10p' /tmp/passwd
#使用sed正则表达式捕获组匹配"123abcxyz",仅保留第一个捕获组"123",输出结果为123。
echo 123abcxyz | sed -r 's/(123)(abc)(xyz)/\1/'
# 提取ens33网卡的IPv4地址
ifconfig ens33 | sed -rn '2s/.*inet ([0-9.]+) .*/\1/p'
# 将 /etc/hosts.bak 文件中每行开头的制表符替换为 # 符号,用于快速注释文件内容。
sed -r 's/^[\t]*/#/' /etc/hosts.bak
四、实战案例
####sed 直接操作文件示例
案列 1
需求:需要将ens33网络接口的IP地址修改为 192.168.10.100
sed -i 's/^IPADDR=.*/IPADDR=192.168.10.100/' /etc/sysconfig/networkscripts/ifcfg-ens33
案列 2
需求:需要将 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
编写一个脚本,用来调整 vsftpd 服务配置,要求禁止匿名用户,但允许本地用户(也允许写入)。
案列3 脚本
[root@lo calhost ~]# vim local_only_ftp.sh
#!/bin/bash
# 指定样本文件路径、配置文件路径
SAMPLE="/usr/share/doc/vsftpd-3.0.2/EXAMPLE/INTERNET_SITE/vsftpd.conf "
CONFIG="/etc/vsftpd/vsftpd.conf"
# 备份原来的在, 若不存在则使用 cp 命令进行配置文件,检测文件名为/etc/vsftpd/vsftpd.conf.bak备份文件是否存文件备份
[ ! -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# 启动vsftpd 服务,并设为开机后自动运行
systemctl restart vsftpd
systemctl enable vsftpd
[root@benet22 ~]# chmod +x local_only_ftp.sh
总结
此卷 “流刃裁文秘术” 已尽传其要,诸位当明:sed
这柄 “流刃”,非寻常工具,实乃 Linux 文本界的 “御文灵宝”—— 其能不止于 “寻字换词、删行留段” 的基础刃法,更可凭 “正则灵韵” 破复杂文阵,以 “脚本编册”(脚本处理)驭多流并发,用 “多卷同裁”(多文件操作)解批量之困,尤擅融入自动化术法(脚本),成批量处理之大功。
修士若能熟用此刃:析日志可 “斩浊留清”,快速揪出天机卷宗中的异常征兆;改配置能 “精准刻符”,不扰法典其他条目;提数据则 “抽丝剥茧”,从灵脉浊流中提纯有用灵力(数据)。此刃虽简,却能以一敌百,为 Linux 修真路上的 “减负至宝”。
望诸位后续勤练 “流刃” 之术,将 sed
的 “随流御刃、精准裁文” 之能融于日常修行,待术法纯熟,自能在系统管理、脚本编程之境更进一阶,成真正的 “御文修士”!