操作
模式空间
保持空间
H
1
\n1
g
\n1
\n1
H
2
\n1\n2
g
\n1\n2
\n1\n2
H
3
\n1\n2\n3
g
\n1\n2\n3
\n1\n2\n3
seq 3 | sed 'h;G' 执行步骤
操作
模式空间
保持空间
h
1
1
G
1\n1
1
h
2
2
G
2\n2
2
h
3
3
G
3\n3
3
seq 3 | sed -n '1!G; h; $p' 执行结果
操作
模式空间
保持空间
1!G
1
h
1
1
$p
---
---
1!G
2\n1
1
h
2\n1
2\n1
$p
---
---
1!G
3\n2\n1
2\n1
h
3\n2\n1
3\n2\n1
$p
3\n2\n1
l 指令
#显示不可打印字符
cat /etc/man.config | head | sed -n 'l'
n和N指令
#打印偶数行,n将下一行的内容读取替换当前行
seq 11 | sed -n 'n; p'
#结果
2
4
6
8
10
#打印基数行,N将下一行的内容读取然后append到当前行后面,P(大写)打印模式空间中第一行
seq 12 | sed -n '$!N; P'
1
3
5
7
9
11
p和P指令
seq 11 | sed -n 'N; P'
seq 12 | sed -n '$!N; P'
#从这两段打印偶数,基数的代码中可以看出p和P(大写)的区别
#p是打印模式空间中所有的内容,而P只打印第一行
q指令
#当匹配 3这行时,退出sed
seq 10 | sed '/3/q;'
r指令
#当匹配10这一行时,读取xx.log文件
seq 10 | sed '/10/r xx.log'
#结果
1
2
3
4
5
6
7
8
9
10
11111
22222
33333333333
4444444444444
ffffff
s指令
#匹配这行第四个和第五个aaa,将其替换为AAA,这里使用了多个匹配
#两个匹配之间用分号分隔, 注意两个匹配式是一样的,因为第一次匹配完之后
#内容就变了
echo "aaa bbb aaa aaa ccc ddd aaa aaa aaa " | sed 's/aaa/AAA/4; s/aaa/AAA/4;'
#匹配这行所有出现的aaa
echo "aaa bbb aaa aaa ccc ddd aaa aaa aaa " | sed 's/aaa/AAA/g'
#匹配第一到第二行,将所有的1替换为!
sed '1,2s/1/!/g' xx.log
#匹配第三行到最后一行,将所有的1替换为!
sed '3,$s/1/!/g' xx.log
t和T指令
#将第三行替换为three,其他行替换为ok
seq 5 | sed 's/3/three/; t lable; s/[0-9]/ok!/; :lable'
#T标签和t相反,当前面的表达式没有匹配时才跳转到lable标签
w指令
#匹配3,将结果写入到xx.log中
seq 5 | sed -n '/3/w xx.log'
x指令
#交换模式空间和保持空间的内容
#第三行的模式空间和保持空间交换后,模式空间为空
#第四行和保持空间交换,此时保持空间内容为3,所以最终模式空间内容变为3
seq 5 | sed '3,4 x;'
#结果
1
2
3
5
y指令
#匹配bbb,替换为BBB
#注意y指令是按字符替换的,所以匹配前的字符和匹配后的字符长度应该相等
echo "aaa bbb ccc" | sed 'y/bbb/BBBB/'
打印当前行号
#当匹配f时,用= 指令打印当前行号
for i in {a..j}; do echo $i; done | sed -n '/f/='
& 符号
# & 符号表示被匹配的变量
for i in {a..j}; do echo $i; done | sed 's/f/---> &
{} 匹配
#匹配a,至少3-5次
echo "xxx aaaaaa fff " | sed 's/a\{3,5\}/!!!/'
#可以用扩展正则表达式实现
echo "xxx aaaaaa fff " | sed -r 's/a{3,5}/!!!/'
\< 和 \>
#匹配k开头的单词,和k结尾的单词
echo "aaa bbb kkk ccc ddd" | sed 's/\/###/'
圆括号匹配
#假设file中都是数字,匹配前两个数字,将十位数,变成个位数+一个小数点和数字
sed 's/\([0-9]\)\([0-9]\)/\1.\2/' file.txt
#上面的() 需要转义,可以用扩展正则表达式来完成同样的功能
sed -r 's/([0-9])([0-9])/\1.\2/' file.txt
多个匹配和子匹配
#匹配多个,也可以用-e 来实现
echo "xxx aaaaaa fff " | sed -r 's/a/A/; s/x/X/; s/ /--/'
#结果
Xxx--Aaaaaa fff
#子匹配,如果匹配3,则执行子匹配, 读取下一行append到模式空间
#如果又匹配4,则再执行子匹配打印当前模式空间内容; 如果匹配5则执行子匹配
#删除当前模式空间内容
seq 5 | sed -n '/3/{N; /4/{p;}; /5/{d}; }'
#结果
3
4
#删除匹配的结果 /[匹配的表达式]/
seq 10 | sed '/3/d'
一些实际的例子
交换奇偶行
seq 10 | sed -n 'x;n;p;x;p'
执行步骤
操作
模式空间
保持空间
x
null
1
n
2
1
p
2
1
x
1
2
p
1
2
另一种方式
seq 10 | sed -n 'h;$!{n;G};p'
操作步骤
操作
模式空间
保持空间
h
1
1
$!{n
2
1
G}
2\n1
1
p
2\n1
1
将所有行合并成一行
seq 10 | sed -n '1{h};1!{H};${g;;s/\n/ /g;p}'
操作步骤
操作
模式空间
保持空间
1{h}
1
1
1!{H}
1
1
${....}
1
1
1{h}
1
1
1!{H}
2
1\n2
${...}
2
1\n2
....
.....
....
${....}
1\n2\n3...
1\n2\n3...
另一种方式
seq 10 | sed -n 'h;:lable n;H;$!{b lable};x;s/\n/ /g;p'
首先执行h,将模式空间内容覆盖到保持空间
之后执行lable标签,n 将下一行的内容覆盖到当前行,然后将模式空间内容append到保持空间
如果不是最后一行,则执行跳转标签继续重复n;H; 执行
到最后一行执行x指令,此时模式空间内容就是1\n2\n3\n4\n..., 再执行s执行替换\n 之后打印
参考
sed(linux指令)
sed的保持空间和模式空间
关于sed的模式空间和保持空间的例子
sed之lable使用详解
sed简明教程
sed系列文件
sed英文手册