1. Sed 概述
1.1 Sed 是什么
Sed 全名为 Stream EDitor,顾名思义是对数据流进行编辑操作的一个命令,它能够遍历文件或文件流,对读入的输入流可以将其先存储在模式空间中,并将行号记录在内存中,利用模式空间中的一系列指定命令对其进行操作,待操作完成后从模式空间输出到 stdout,类似于在一个管道在其中对数据进行加工,完成后从另一头输出,接着读取下一行,重复往返,直至将所有标准输入读取处理完成。
1.2 为什么用 Sed
Sed 相较于 grep/awk,其主要功能为对文件进行修改处理,可以对文件或标准输入数据流进行增删改查等操作,尤其适用于大文件或有规律的文件,利用此工具,能够帮助我们快捷的在编写 Shell 脚本中得心应手的对文件进行操作。
2. Sed 的适用场景
超大文件处理;
有规律的文本,例如格式化后的日志文件等;
对文件进行批量增加,替换等。
3. Sed 的处理模式
Sed 对输入的一行数据进行处理的模式,对整个文件进行重复执行此模式处理,在此说明对输入的一行数据处理的内在机制如下图所示:
首先读入文件流的一行到模式空间;
在模式空间内,对内容进行模式匹配处理;
输出处理后的数据内容;
清空当前模式空间;
读取第二行输入流到模式空间;
又开始对模式空间内的下一行输入数据进行处理。
4. 语法详解
sed 语法格式如下图所示:
- 1
sed 的语法格式主要分为四个字段,options 选项,引号内有地址定界 / 命令,以及要处理的文件,接下来让我们详细讲解每一个语法字段,更全面的认识 sed 这个脚本利器。
4.1 options:
选项为可选,利用它来为 sed 指定一些处理方式,主要的有如下:
- -n: 静默模式,我们知道 sed 默认处理完模式空间后将内容输出到标准输出,利用这个这个参数仅显示 script 处理后的结果,不再默认显示模式空间中的内容,例如:打印 /etc/passwd 的第三行
- 1
- 2
在此直接指定地址定界 3,然后 command 为 p 打印输出,由于不想输出 /etc/passwd 的全部内容,因此添加了 - n 选项。
- 1
- 2
- 3
- 4
4.2 address:
地址定界用来指定读入文件的边界或步长。
startline,endline
:指定读入文件的开始行于结束行号。/regexp/
: 利用正则表达式匹配到的行进行处理,例如:打印 /etc/passwd 从以 root 开始到 sync 结束的内容
- 1
- 2
- 3
- 4
- 5
- 6
- 7
在此利用了匹配元字符 ^
用来匹配行首,此内容在正则表达式中已经进行了详细解释。
/pattern1/,/pattern2/
: 第一次被 pattern1 匹配到的行开始,直到被 pattern2 匹配到的行结束,例如:打印 /etc/passwd 的第四行到第七行的内容
- 1
- 2
- 3
- 4
- 5
- 6
linenuber
: 直接指定行号,需要处理哪一行。startline,+n
: 从那一行开始,往后 n 行结束,例如:打印 /etc/passwd 的从第三行开始往后的 2 行的内容
- 1
- 2
- 3
- 4
startline~step
: 指定步长,每隔 step 步进行处理,常用在奇偶数处理,例如:打印奇数行
- 1
seq 来输出以数字为内容的 10 行,然后利用 ~2
作为步长打印输出。
4.3 command:
具体对指定的文件进行怎样的处理,例如对模式空间内的内容进行增删改查具体的操作。
4.3.1 增
- i:insert,在制定或匹配到的行前面添加新行内容为 string,
i\string
,
为 /etc/passwd 中的第一行前面添加一行内容为 "####",例如:
- 1
- 2
- 3
- 4
- 5
- 6
- a:append,在指定或匹配到的行后面追加新行,内容为 string,
a\string
。
为 /etc/passwd 的第一行后面添加内容 "aaa",例如:
- 1
- 2
- 3
- 4
- 5
- 6
4.3.2 删
- d:delete,删除符合地址定界条件的的行
删除 /etc/inittab 文件中注释行,例如:
- 1
直接利用元字符匹配铆定以#
开头的行进行删除操作,注意此处没有直接修改文件,如果添加 -i
选项,则直接对源文件进行修改,一般需要先备份,然后操作以免误操作原始文件。
4.3.3 改
- s:
s/pattern/string/修饰符
: 查找并替换,默认只替换每行中第一次被模式匹配到的字符串 ,如果修饰符为 g, 则为全部替换。
替换 /etc/passwd 中的 root 为大写,例如:
- 1
- 2
- 3
- 4
- 5
替换 /etc/inittab 文件中 "id:3:initdefault:" 一行中的数字为 5,例如:
- 1
在此利用元字符匹配 [0-9] 的一个数字进行替换为 id:5
。
4.3.4 查
- p:print,默认 sed 对模式空间内的处理完毕后,将输出的结果输出在标准输出,添加 p 命令,相当于输出了原文,又一次输出了模式匹配处理后的内容。
打印 /etc/passwd 的第三行,指定行号,例如:
- 1
- 2
在此直接指定地址定界 3,然后 command 为 p 打印输出,由于不想输出 /etc/passwd 的全部内容,因此添加了 - n 选项。
5. 实例
5.1 需求
目前腾讯云服务器 Ubuntu 版本用户为 ubuntu 用户,现又 1000 台服务器需要去开启 root 远程登录。
5.2 思路
开启 ubuntu 服务器的远程登录即修改其的 /etc/ssh/sshd_config 文件的 prohibit-password 为 yes 即可,重启 sshd 服务即可,利用脚本逻辑处理。
5.3 实现
核心利用 sed 代码:
- 1
- 2
- 3
- 4
- 5
- 6
6. 注意事项
- sed 中利用于正则表达式配合可以得到 1+1 大于二的效果,配合使用功能更加丰富强大;
- sed 常用于修改文件,如果为查询文件可以利用 grep,因为 grep 检索文件效率最高,如果为格式化输出建议使用 awk;
- sed 在修改文件的时候尽可能先不要添加
-i
options,以免将源始文件修改异常难以恢复。
7. 小结
sed 的功能非常强大,它是我们 shell 编程中对文件修改不可或缺的利器,配合正则表达式常用来批量修改大文件,或有一定格式规律的文件,其还有很多高级功能。如果学有余力建议去 man 手册详细学习查看,在利用 sed 工具的时候需要时刻脑海中牢记求语法格式,万变不离其宗,遵循语法举一反三能够达到学生事半功倍的效果。