虽然之前对常用的 Linux 命令有过一个总结 工作中常用的 Linux 命令,但是有一些命令的用法确实值得为她单独写一篇总结。今天我们就来认识一下 sed。
概述
sed
是一个流编辑器(stream editor
,或许,sed
缩写的含义就是这个)。流编辑器用于对输入流(文件或来自管道的输入)执行基本的文本转换。 sed在管道中过滤文本的能力,这使其与其他类型的编辑器特别有区别。
地址定界符
今天看到一个 sed
的写法,sed 's#^key##'
,一开始没看明白,因为之前都是类似 sed 's/^//'
这样写的。后来查了资料才发现,/、#、@
都是地址定界符,效果是一样的。
增加
1 | [root@607bac0e5f20 demo]# sed -i '1i demo learn' demo.txt |
说明:
-i
参数加上之后,会去「就地」修改demo.txt
这个文件,不加的话,demo.txt
的内容不会被修改;1i
表示文件第1行内容加上内容,i
效果是读取第一行之前增加include
记录。有点VIM
的i
的效果;2a
表示文件第2行捏偶人后面加上内容,a
效果就是读取此行之后增加append
记录。优点VIM
的a
的效果;$
表示文件尾,在最后一行增加,则可用$a
表示;
如果需要在匹配的地方增加一行,可以:1
2
3
4
5
6
7[root@607bac0e5f20 demo]# sed -i '/michael/i michael is michael' demo.txt
[root@607bac0e5f20 demo]# cat demo.txt
sed demo learn
michael is michael
hello michael
sunny smile
hello qq
说明:
- 上面这里的
/michael/i
这里的i
当然也可以换成a
,那么,插入的位置会有不同; - 如果插入的行以空格开头,可用
\
来转义这个空格 - 如果多行都满足匹配条件,那么就会多出插入内容;
- 如果插入的内容要换行,可用
\n
表示换行符,可以实现插入2行的效果
删
删除和增加差不多,只需要把 i
或 a
替换为 d
。
示例文本内容如下:1
2
3
4
5
6[root@607bac0e5f20 demo]# cat -n demo.txt
1 sed demo learn
2 michael is michael
3 hello michael
4 sunny smile
5 hello qq
把第1行删除:1
2
3
4
5[root@607bac0e5f20 demo]# sed '1d' demo.txt
michael is michael
hello michael
sunny smile
hello qq
将和 michael
匹配的行删除:1
2
3
4[root@607bac0e5f20 demo]# sed '/michael/d' demo.txt
sed demo learn
sunny smile
hello qq
将 smile
匹配行和其下一行内容删除:1
2
3
4[root@607bac0e5f20 demo]# sed '/smile/{N;d}' demo.txt
sed demo learn
michael is michael
hello michael
说明:
- 这里的
N
表示next line
的意思。
如果不想删除 smile
这行,仅仅是删除 smile
匹配行的下一行呢?
1 | [root@607bac0e5f20 demo]# sed '/smile/{N;s/\n.*//}' demo.txt |
说明:
s/\n.*//
这里表示匹配了下一行的内容,然后用空字符替换掉了这一行,即实现了删除下一行的效果
改、替换
示例文本内容如下:1
2
3
4
5
6[root@607bac0e5f20 demo]# cat -n demo.txt
1 sed demo learn
2 michael is michael
3 hello michael
4 sunny smile
5 hello wheel
每行开头增加 China,
的内容:1
2
3
4
5
6[root@607bac0e5f20 demo]# sed 's/^/China,/' demo.txt
China,sed demo learn
China,michael is michael
China,hello michael
China,sunny smile
China,hello wheel
说明:
s
表示substitute
,替换的意思;^
表示一行的开头,行尾用$
表示,又和VIM
的操作一样;
扩展:
1 | \< 表示词首。 如:\<abc 表示以 abc 为首的詞。 |
将所有的 michael
替换为 `Michael:1
2
3
4
5
6[root@607bac0e5f20 demo]# sed 's/michael/Michael/g' demo.txt
sed demo learn
Michael is Michael
hello Michael
sunny smile
hello wheel
说明:
g
代表整行范围内的所有匹配全部替换,如果不加,那么只会匹配每一行第一个匹配的内容,比如,文本第二行,有两个michael
,如果不加g
,那么,第二个michael
将不会 ->Michael
。如果用2
的话,则表示只替换第 2 个匹配项。还可以用i
忽略大小写
如果想让匹配的内容后面加上指定字符呢,比如,上面文本中, el
匹配的后面加上 -dev
的字符:1
2
3
4
5
6
7
8
9
10
11
12[root@607bac0e5f20 demo]# sed 's/el/&-dev/g' demo.txt
sed demo learn
michael-dev is michael-dev
hel-devlo michael-dev
sunny smile
hel-devlo wheel-dev
[root@607bac0e5f20 demo]# sed -r 's/(el)/\1-dev/g' demo.txt
sed demo learn
michael-dev is michael-dev
hel-devlo michael-dev
sunny smile
hel-devlo wheel-dev
说明:
- 第一种方法中,
&
表示匹配上的内容; - 第二种方法,
-r
表示扩展的正则表达式,圆括号表示分组,第一个圆括号是第一组,替换的时候则用\1
表示,一次类推;
将2-3行的 michael
替换为 xiang
:
1 | [root@607bac0e5f20 demo]# sed '2,3s/michael/xiang/g' demo.txt |
将第2行的内容替换为 hello mike
:1
2
3
4
5
6[root@607bac0e5f20 demo]# sed '2s/.*/hello mike/g' demo.txt
sed demo learn
hello mike
hello michael
sunny smile
hello wheel
使用变量的值用于替换的表达式中,需要用双引号:1
2
3
4
5
6
7
8
9[root@607bac0e5f20 demo]# name=Michael
[root@607bac0e5f20 demo]# echo $name
Michael
[root@607bac0e5f20 demo]# sed "s/wheel/${name}/g" demo.txt
sed demo learn
michael is michael
hello michael
sunny smile
hello Michael
说明:
- 如果不用双引号,那么,文本最后一行将会是这样的
hello ${name}
;
删除所有的符号:
1 | [root@607bac0e5f20 demo]# cat demo.txt |
说明:
[[:punct:]]
是正则表达式中预先定义的子字符类(character classes
),代表所有的标点符号。sed 支持的子字符类如下:
1 | :alnum:]:[0-9A-Za-z] |
参考
- 官宣-sed, a stream editor 权威文档
- CoolShell-SED 简明教程
- 看例子学sed
- growing-up/doc/三十分钟学会SED.md