跳转至

sed 文件流编辑器

概要: sed(stream editor)是Linux三剑客之一,常用于自动化程序的文本处理工作。

创建时间: 2022.12.18 21:39:04

更新时间: 2023.07.28 23:08:40

sed工作原理

不同于大名鼎鼎的vim,sed是一种流编辑器,它使用预先设定好的编辑命令对输入的文本进行编辑,完成后输出编辑结果
工作原理

  1. 从输入文件中读取内容,每次只读取一行文件,并将其存储到临时的缓存区,即模式空间
  2. 使用输入的sed命令处理此行文本
  3. 处理完毕此行文本后,将缓存区中内容输出到屏幕
  4. 继续处理下一行,直到文件结束

提示

在不使用重定向输入工具的情况下,sed不会更改原始文件(除非使用-i参数)

正则表达式

参考三剑客之一grep工具:在grep工具中,使用正则表达式 | LZWANG的博客

sed语法

基本语法

Bash
sed [option] 'command' filename

命令参数选项

参数 说明
-n 安静模式,加上此参数不会将处理后的文本结果输出到屏幕
-i 修改原文件,加上此参数sed将直接对原始文件进行修改
-e 一次对目标文件执行多条子命令
-f 执行指定文件sed脚本命令
-r 使用扩展正则表达式ERE,而不是基本正则表达式BRE

提示

在macOS系统中,如果使用 sed -i 命令,相比于Linux系统需要在 -i 参数后加上一个空字符串,不然将无法修改源文件。
如在Linux上 sed -i 's/a/b/g' file.txt
那么在macOS上需要改为 sed -i '' 's/a/b/g' file.txt

定址操作

默认情况下sed会对文件的每一行进行操作,如果需要处理特殊的几行文本,需要进行定址操作。
假设我们有一个名为test.txt的文件,内容如下

Text Only
1
2
3
4
5
6
7
hello world

hello here

hello there

hello world

如果不使用定址,直接使用sed执行如下替换操作
Bash
sed 's/hello/hi/g' test.txt
输出为

数字定址

数字定址即使用数字行数来确定要操作的行

某一行

Bash
# 将第3行进行替换
sed '3s/hello/hi/g' test.txt

连续几行

Bash
# 将第1-3行进行替换
sed '1,3s/hello/hi/g' test.txt

从某一行起的后几行

此命令macOS报错

Bash
# 将第3行及后4行(第3-7行)进行替换
sed '3,+4s/hello/hi/g' test.txt
macOS系统

Linux系统

除去某一行的剩余行

Bash
# 将第3行之外其余所有行进行替换
sed '3!s/hello/hi/g' test.txt

正则定址

正则定址即使用正则表达式来确定要操作的行。

匹配特定字符串

Bash
# 匹配到带有world的行并删除
sed '/world/d' test.txt

匹配空行

Bash
# 删除空行
sed '/^$/d' test.txt

匹配字符串1和字符串2之间的所有行

Bash
# 删除here结尾至world结尾行之间的所有行
sed '/here$/,/world$/d' test.txt

子命令

替换字符串子命令s

基本语法:[address]s/pattern/rep/flags
将示例的文本文件改写如下:

Text Only
1
2
3
4
5
6
7
hello world hello

hello here hello hello hello

hello there

hello world

只替换行内匹配到的第一个

Bash
# 将每一行第一个hello换成hi
sed 's/hello/hi/' test2.txt

替换行内所有匹配到的

Bash
# 将每一行所有hello换成hi
sed 's/hello/hi/g' test2.txt

只替换某一个匹配到的

Bash
# 将每一行第二个hello换成hi
sed 's/hello/hi/2' test2.txt

替换某一个之后匹配到的

macOS此命令报错,Linux正常

Bash
# 将每一行第二个之后(第3个及以后)hello换成hi
sed 's/hello/hi/3g' test2.txt
macOS

Linux

在行首添加内容

Bash
# 将每一行行首添加123字符串
sed 's/^/123/g' test2.txt

在行尾添加内容

Bash
# 将每一行行尾添加123字符串
sed 's/$/123/g' test2.txt

匹配多个字符串并替换

Bash
1
2
3
4
# 将1-3行的hello替换成hi,且第3行后的world替换为tomorrow
sed '1,3s/hello/hi/g; 3,$s/world/tomorrow/g' test2.txt
# 等价命令
sed -e '1,3s/hello/hi/g' -e '$s/world/tomorrow/g' test2.txt

将匹配到的字符串改写

Bash
# 将hello两端加上双引号
sed 's/hello/"&"/g' test2.txt

只打印修改的行

Bash
# 将hello两端加上双引号,并只打印改动的行 /p
sed -n 's/hello/"&"/p' test2.txt

匹配时忽略大小写

macOS会报错

Bash
# 将hello两端加上双引号,并只打印改动的行 /i
sed -n 's/hello/"&"/i' test2.txt
macOS

Linux

替换行子命令c

此命令用于将整行替换为自己的文本。

替换所有行

Bash
# 将所有行替换为12345
sed 'c 12345' test2.txt

替换某几行

Bash
# 将1-3行替换为12345(三行变成一行)
sed '1,3c 12345' test2.txt

分别替换几行

Bash
# 将1-3行分别替换为12345(使用换行符解决)
sed '1,3c 12345\n12345\n12345' test2.txt

追加行子命令a

追加所有行

Bash
# 将所有行后追加一行12345
sed 'a 12345' test2.txt

追加某几行

Bash
# 将1-3行后追加一行12345
sed '1,3a 12345' test2.txt

插入行子命令i

可以视作追加的反操作(即在指定行前追加行)

Bash
# 将1-3行前插入一行12345
sed '1,3i 12345' test2.txt

删除行子命令d

删除指定几行

Bash
# 将1-3行删除
sed '1,3d' test2.txt

删除正则匹配行

Bash
# 将there结尾的行删除
sed '/there$/d' test2.txt

设置行号子命令=

在行上方插入行号

Bash
# 在1-3行上插入行号
sed '1,3=' test2.txt

在行前插入行号

Bash
# 在所有行前插入行号,与行内容间隔两个空格
sed '=' test2.txt | sed 'N;s/\n/  /'

参考