命令汇总
指令 | 含义 |
a | 在当前行后面加入一行文本 |
b lable | 跳转分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末 |
c | 用新的文本改变本行的文本 |
d | 从模式空间(Pattern space)位置删除行 |
D | 删除模板块的第一行 |
i | 在当前行上面插入文本 |
h | 拷贝模式空间的内容到保持空间(hold space),替换之前的内容 |
H | 将模式空间的内容追加到保持空间,追加为\n |
g | 获取保持空间中的内容,并覆盖当前模式空间的内容 |
G | 后去保持空间中的内容,将内容追加到模式空间之后 |
l | 列出不能打印的字符 |
n | 读取下一行的内容,替换当前行 |
N | 读取下一行的内容,追加到当前行之后,即 \n 下一行的内容 |
p | 打印模式空间的内容 |
P(大写) | 打印模式空间的第一行 |
q | 退出sed |
r file | 从指定的文件中读取内容 |
s | s/re/string 用string替换正则表达式re,s/re/string/g 表示替换所有处 |
t lable | 如果之前的模式满足条件,则执行t 并跳转到指定的标签出,如果t 没有 标签则跳转到表达式最后(也就是结束什么都不做) |
T lable | 和t 指令相反,当前面的模式没有满足条件时,才进行跳转 |
w file | 将模式空间中的内容append到指定的文件后 |
W file | 将模式空间中的第一行append到指定的文件后 |
x | 互换模式空间和保持空间的内容 |
y | 类似tr命令,y/old/new/ 将old替换成new,这里是按字母匹配的,所以 old和new的长度必须一样 |
选项
扫描二维码关注公众号,回复:
1595106 查看本文章
选项 | 含义 |
-e | 进行多项编辑,即对输入行应用多条sed命令时使用 |
-n | 取消默认的输出 |
-f | 指定sed脚本的文件名(sed的表达式放在一个文件中) |
-r | 使用扩展正则表达式 |
元字符集
元字符 | 含义 |
^ | 锚定行的开始如:/^sed/匹配所有以sed开头的行 |
$ | 锚定行的结束 如:/sed$/匹配所有以sed结尾的行 |
. | 匹配任意一个字符 |
[] | 匹配指定范围内的字符 |
\(..\) | 保存匹配的字符,如s/\(love\)able/\1rs,\1可以引用第一个圆括号的内容 |
& | 用来当做被匹配的变量 |
\< | 锚定单词的开始,如:/\<love/匹配包含以love开头的单词的行 |
\> | 锚定单词的结束,如/love\>/匹配包含以love结尾的单词的行 |
x\{m\} | 重复字符x,m次,如:/0\{5\}/匹配包含5个o的行 |
x\{m,\} | 重复字符x,至少m次,如:/o\{5,\}/匹配至少有5个o的行 |
x\{m,n\} | 重复字符x,至少m次,不多于n次,如:/o\{5,10\}/匹配5--10个o的行 |
指令详解
a指令
- #在所有行后增加...
- seq 10 | sed 'a ......'
- #在2,3行之后增加 ??
- seq 10 | sed '2,3 a ??'
b指令
- #如果是匹配 3则只在最后增加 !!!,其他行在尾后增加@@@和 !!!
- #b标签是强制跳转,不像t标签满足条件后才跳转,b是任何情况下都跳转
- seq 10 | sed '/3/b lable; s/$/ @@@/; :lable s/$/ !!!/'
- #结果
- 1 @@@ !!!
- 2 @@@ !!!
- 3 !!!
- 4 @@@ !!!
- 5 @@@ !!!
- 6 @@@ !!!
- 7 @@@ !!!
- 8 @@@ !!!
- 9 @@@ !!!
- 10 @@@ !!!
i指令
- #在第三行之前增加 ???
- seq 10 | sed '3 i ???'
- #在第一到第五行之前增加hehe
- seq 10 | sed '1,5 i hehe'
- #如果是8开头的,则在这行之前增加hehe
- seq 10 | sed '/^8/ i hehe'
h,H,g,G指令
- seq 3 | sed 'H;g'
- #结果为
- 1
- 1
- 2
- 1
- 2
- 3
- seq 3 | sed 'h;G'
- #结果
- 1
- 1
- 2
- 2
- 3
- 3
- seq 3 | sed -n '1!G; h; $p'
- #结果
- 3
- 2
- 1
seq 3 | sed 'H;g' 执行步骤:
操作 | 模式空间 | 保持空间 |
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/\<k/***/; s/k\>/###/'
圆括号匹配
- #假设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 之后打印
参考