sed编辑器
sed编辑器
前言
sed是一种流编辑器,流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流
sed编辑器可以根据命令来处理数据流中的数据,这些命令要么从命令行中输入,要么存储在一个命令文本文件中
工作流程
sed的工作流程主要包括读取、执行和显示三个过程∶
读取∶ sed从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)
执行; 默认情况下,所有的sed 命令都在模式空间中顺序地执行,除非指定了行的地址,否则sed命令将会在所有的行上依次执行
显示∶ 发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完
在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。
注意:默认情况下所有的sed命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出。
命令格式
sed [选项] ‘操作’ 文件名
sed -e ‘操作’ 文件1 文件2 .....
sed -n -e ‘操作’ 文件1 文件2 .....
sed -f 脚本文件 文件1 文件2 .....
sed -i -e ‘操作’ 文件1 文件2 .....
sed -e ‘n{
操作1
操作2
.........
}’ 文件1 文件2......
常用选项
-e或--expressidn=∶表示用指定命令来处理输入的文本文件,只有一个操作命令时可省略,一般在执行多个操作命令使用
-f或--file=∶表示用指定的脚本文件来处理输入的文本文件
-h 或--help∶显示帮助
-n、--quiet 或 silent∶禁止sed编辑器输出,但可以与p命令一起使用完成输出
-i∶直接修改目标文本文件
常用操作
s∶替换,替换指定字符
d∶删除,删除选定的行
a∶增加,在当前行下面增加一行指定内容
i∶插入,在选定行上面插入一行指定内容
c∶替换,将选定行替换为指定内容
y∶字符转换,转换前后的字符长度必须相同
p∶打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以ASCII码输出。其通常与"-n"选项一起使用
=∶打印行号
l(小写L)∶打印数据流中的文本和不可打印的ASCII字符(比如结束符s、制表符\t)
打印内容
sed -n -e 'p' 1.txt (进行'p'打印操作如果不使用-n禁止sed编辑器输出,会每行打印两遍)
sed -n -e'=' 1.txt(只打印出行号)
sed -n -e 'l' 1.txt(打印数据和ASCII码,数据每行结束的ASCII码就是$符号)
sed -n -e '=;p' 1.txt 或 sed -n -e'=' -e 'p'1.txt (打印出行数以及内容)
使用多行格式书写也可以实现
sed -n '
>=
>p
> ' testfilel
使用地址寻找
sed编辑器有2种寻址方式:
1.以数字形式表示行区间
2.用文本模式来过滤出行
示例:
sed -n '1p' 1.txt(打印第一行内容)
sed -n '$p' 1.txt(打印最后一行内容)
sed -n '1,3p' 1.txt(打印1-3行内容)
sed -n '3,$p' 1.txt(打印第3行到最后一行的内容)
sed -n '1,+3p' 1.txt(打印1之后的连续3行,即1-4行)
sed '5q' 1.txt(打印前5行信息后退出,q表示退出)
sed -n 'p;n' 1.txt(打印奇数行; n表示移动到下一行,当sed执行完打印第一行后n移动到下一行到第二行,当sed执行完所有操作后默认往下移动一行开始编辑执行,所以就从第二行移动到了第三行开始执行)
sed -n 'n;p' 1.txt (打印偶数行,先执行移动到下一行的操作)
sed -n '2,${n;p}' 1.txt(从第二行开始到最后一行每次往下移动一行打印)
sed -n '5,${n;p;n}' 1.txt(从第五行开始到最后一行,每次移动一行打印之后再向下移动一行,执行完后sed命令默认从下一行开始,所以第一次为6第二次为9)
sed -n '/user/p' /etc/passwd(从/etc/passwd这个文件中打印包含user这个字符的所有行,这里的users并不是一个整体字符,所以即时某个字符中包含user也会打印)
sed -n '/^a/p' /etc/passwd(打印所有以a开头的行)
sed -n '/bash$/p' /etc/passwd(打印所有以/bash结尾的行)
sed -n '2,/nobody/p' /etc/passwd(从第二行打印到第一个包含nobody的行)
sed -n '2,/nobody/=' /etc/passwd(打印第二行到第一包含nobody行的行号)
sed -n '/ftp\|root/p' /etc/passwd(打印包含ftp或者root的行,|为特殊字符需要加上\转义字符)
sed -nr '/ro{1,}t/p' /etc/passwd(-r表示支持扩展正则表达式)
或者sed -n '/ro\{1,\}t/p' /etc/passwd打印出匹配字符o一次及一次以上的行
删除行
sed 'd' 1.txt(全删)
sed '3d' 1.txt (删除第三行)
sed '2, 4d' 1.txt(删除2-4行)
sed '$d' 1.txt(删除最后一行)
sed '/^$/d' 1.txt(删除空行)
sed '/nologins$/d'/etc/passwd(删除以nologin结尾的行)
sed '/nologin$/!d'/etc/passwd("!"表示取反操作,就是除了nologin结尾的都删除)
sed '/\/bin\/bash$/!d'/etc/passwd(除了/bin/bash所在的行都会被删除,如果删除的字符本事有/符号需要加上\转义符)
(sed '/第一个位置/,/第二个位置/d' 文件名)从第一个位置打开行删除功能,到第二个位置关闭行删除功能,如果再次匹配到符合第一位置的字符将再次启动删除功能,直到匹配到符合第二个位置的字符,以此类推第三次、第四次,如果没有始终没有匹配第二个位置的字符将一删到底
sed '/2/,/3/d' 1.txt(从包含数字2的行删除到包含数字3的行)
sed '/1/,/3/d' 1.txt(从包含数字1的行删除到包含数字3的行)
替换
格式:sed [选项] '行范围 s/旧字符串/新字符串/替换标记' 文件名
4种替换标记
数字∶表明新字符串将替换第几处匹配的地方
g∶表明新字符串将会替换所有匹配的地方
p∶打印与替换命令匹配的行,与-n一起使用
w 文件∶将替换的结果写到文件中
sed -n 's/root/ADC/p' /etc/passwd(匹配到包含root的行并且替换为ADC,每行只会替换第一个符合要求的字符,后面的则不会)
sed -n 's/root/ADC/2p' /etc/passwd(每行替换第二次匹配到的旧字符为ADC,如果这行只匹配到一次没有第二次匹配到的旧字符那就不会进行替换)
sed -n 's/root/ADC/gp'/etc/passwd (匹配到所有的旧字符都换为新字符)
sed -n 's/root//gp'/etc/passwd(也能启到删除的作用)
sed '1,20 s/^/#/' /etc/passwd(1-20行开头部分替加上#符号)
sed '/^root/ s/$/#/' /etc/passwd(将以root为开头的行结尾加上#,-n没有组织sed编辑器输出即可将未修改的部分也显示)
sed -f 2.sed 2.txt(预先将需要执行的操作写到脚本文件中,直接进行替换)
sed '1,20 s/^/#/w 3.txt' /etc/passwd(将1-20行开头加上#并且将结果保存到3.txt这个文件中,可以加-n不输出直接去文件里查看,文件里只会显示替换的部分)
在使用sed编辑器替换时如果旧字符和新字符也包含多个/,就会和原本替换格式的/冲突,需要加上\,虽然可以实现但是看上去很乱;所以这种情况可以将替换格式里的/定义为任意字符,格式本身所有的/都为相同的字符,保持一致即可)
sed -n 's/\/bin\/bash/\/bin/\/cah/p' /etc/passwd(虽然可以实现但看上去很乱)
sed -n 's!/bin/bash!/bin/csh!p' /etc/passwd(可以使用!作为字符串分隔符,一样可以实现,只要前后都保持一致即可)
sed 's9\945\9\99\98\939g' /etc/passwd(将94599替换为9893,这里将/替换为9,而\9则代表数字9为了和字符串分隔符区分开来,所以所有\9都是数字9,单个9为字符串分隔符也就是原来的/)
插入
sed -e '/3/c ABC' -e '/5/c ABC' 2.txt(将包含数字3和包含数字5替换为ABC)
sed 'y/1/A/' 2.txt(将每行包含1的替换为A,y表示替换前后字符长度必须一致)
sed '1,2y/1/A/' 2.txt(将1-2行里包含数字1的替换为A)
sed '1, 3a ABC' 2.txt(在1-3行后面插入ABC)
sed '1i ABC' 2.txt(在第一行前面插入ABC)
sed '3r /root/1.txt' 2.txt(将/root/1.txt文件里的内容插入到第三行后面,r表示在某一处插入某个文件内容)
sed '2{H;d};$G' 2.txt(将第二行的内容剪切到末尾,H表示复制到剪切板,d表示删除,G表示粘贴到指定行后,默认空一格开始输出)
sed '/2/{H;d};4G' 2.txt(将包含数字2的行的内容剪切到第四行后面)
echo "112233"l sed -r 's/(11)(22)/\2\1/'(将字符111和222互换位置,这里的\2代表的前面(222)的位置,-r表示支持扩展正则表达式)
这个会按照顺序进行匹配,所以如果需要定义后面的字符需要将前面的都写出了
echo "112233"l sed -r 's/^(.)(.*)(.)$/\3\2\1/'(将第一个字符和最后一个字符互换)