你所不知道的那些sed命令
sed 全名 stream editor,一般用于文本内容替换。本文介绍日常工作中常用到的 sed 命令,更加完整的说明可以点击文末阅读原文参考 sed 手册。
01—模式空间(pattern space)
-
将文件以
行
为单位读取到内存(模式空间) -
使用 sed 的
每个脚本
对该行进行操作 - 处理完成后输出该行
如下所示,读取 a.log 文件第一行内容,sed 中有 2 个替换脚本,第一个将 aa 替换成 @@ ,第二个将 bb 替换成 !! ,最后输出结果。
meng➜/tmp» cat a.log
aa bb cc
meng➜/tmp» sed 's/aa/@@/;s/bb/!!/' a.log
@@ !! cc
02—替换命令 s
字符串替换,将文件中 src 字符串替换成 new,支持多个替换脚本
sed ’s/src/new/‘ filename
sed -e ’s/src/new/’ -e ’s/src1/new1/‘ filename
# 这里等同于下面分号隔开
sed 's/src/new/;s/src1/new1/' filename
默认只会输出替换后的文本,
-i
可以直接将源文件修改掉。
sed -i 's/src/new/' filename
正则替换:最常用的替换方式,需要你对正则表达式比较熟悉。
sed ’s/正则表达式/new/‘ filename
sed -r ’s/扩展正则表达式/new/ filenam
# 每行前面添加 #
sed 's/^/#/' filename
扩展正则表达式包括 ?, +, |, ( ) 这几个字符
在扩展正则表达式中,使用圆括号匹配的内容可以当做变量来使用。比如我们可以将 aa 字符前加两个 !!
meng➜/tmp» sed -r 's/(aa)/!!\1/' a.log
!!aa bb c
03—标志位
s/src/new/标志位 `` - g:每次出现都替换。 - 数字:替换第几次出现,可以数字+g 替换第几次之后。 - p:打印模式空间内容
默认每行只会替换匹配的第一个,我们可以通过 g 来替换所有
meng➜/tmp» cat b.log
aa aa aa aa
meng➜/tmp» sed 's/aa/@@/g' b.log
@@ @@ @@ @@
meng➜/tmp» sed 's/aa/@@/2' b.log
aa @@ aa aa
meng➜/tmp» sed 's/aa/@@/2g' b.log
aa @@ @@ @@
p 将匹配的内容进行再次打印。加 p 后匹配的内容会被打印两次,第一次是标准输出,第二次是模式空间内容输出。这个可以结合 -n 使用,-n 表示处理完不进行标准输出。比如:在测试命令的时候,文件行数非常多,我只关心命令生效的内容。
meng➜/tmp» cat c.log
aa aa aa aa
bb bb
meng➜/tmp» sed 's/aa/@@/p' c.log
@@ aa aa aa
@@ aa aa aa
bb bb
meng➜/tmp» sed -n 's/aa/@@/p' c.log
@@ aa aa aa
04—寻址
sed 默认对每行进行操作,增加寻址后仅对匹配的行进行操作。
- /正则表达式/s/src/new/g。
- 行号s/old/new/g。行号可以是具体的行,也可以是最后一行 $ 符合。
- 可以使用两个寻址符号,也可以混合使用行号和正则。
- /正则表达式/{ s/src/new;s/src/new/ },多个替换命令。
meng➜/tmp» cat d.log
aa aa
11 aa
cc aa
meng➜/tmp» sed '/^[a-z]/s/aa/@@/' d.log
@@ aa
11 aa
cc @@
meng➜/tmp» sed '2s/aa/@@/' d.log
aa aa
11 @@
cc aa
meng➜/tmp» sed '2,3s/aa/@@/' d.log
aa aa
11 @@
cc @@
meng➜/tmp» sed '/^[a-z]/,$s/aa/@@/' d.log
@@ aa
11 @@
cc @@
/^[a-z]/,$s/ 从 /^[a-z]/ 匹配的行开始,一直到最后一行
05—其他
d 删除匹配的行
meng➜/tmp» sed '/11/d' d.log
aa aa
cc aa
a 追加
# 在匹配的行后追加字符串 hello
meng➜/tmp» sed '/11/a hello' d.log
aa aa
11 aa
hello
cc aa
i 插入
meng➜/tmp» sed '/11/i hello' d.log
aa aa
hello
11 aa
cc aa
c 更改
# 相当于直接替换掉这一行
meng➜/tmp» sed '/11/c hello' d.log
aa aa
hello
cc aa
p 打印
# 打印长度为 6 的回文串
meng➜/tmp» sed -rn '/(.)(.)(.)\3\2\1/p' word.log
redder
06—多行匹配
有了 N 、P 、D 我们就可以多行内容一起处理了。
- N 将下一行加入到模式空间。
- D 删除模式空间中的第一个字符到第一个换行符。
- P 打印模式空间中的第一个字符到第一个换行符。
meng➜/tmp» cat e.log
# 将第二行合并到第一行,然后将换行符删掉
meng➜/tmp» sed 'N;s/\n//' e.log
hello
接下来看个示例,hello meng 被换行分隔成了多行,将它合并成一行,并替换成 hello sed。
meng➜/tmp» cat f.log
o meng hel
lo meng
# 处理流程见下图
meng➜/tmp» sed 'N;s/\n//;s/meng/sed\n/;P;D' f.log
hello sed
hello sed
07—保持空间(hold space)
保持空间也是一块暂存区域,我们可以将模式空间的内容复制到保持空间,也可以将保持空间内容复制到模式空间,方便我们对多行进行操作。
- h 和 H 将模式空间的内容存放到保持空间,小写是覆盖模式,大写是追加模式。
- g 和 G 将保持空间的内容取出到模式空间,大小写含义同上。
- x 交换模式空间和保持空间内容。
保持空间默认有一个初始字符:换行符
看个示例,tac 命令是将文件倒序输出,用 sed 怎么实现呢?
➜ /tmp cat g.log