Linux命令之sed(流编辑器)
sed流编辑器是一行一行的处理文件内容的,正在处理的内容存放在模式空间(缓冲区)内,处理完成后按照选项的规定进行输出或文件的修改。除非使用重定向存储输出,否则文件内容不会发生改变。
sed主要用于自动编辑一个或多个文件,简化对文件的反复操作。并且sed也支持正则表达式,如果想使用扩展正则需要添加参数-r。
sed [选项] [附加命令] [输入文件]
(1).选项
-n,--quiet,--silent 取消自动打印模式空间内容 -e [附加命令],--expression=[附加命令或脚本] 添加附加命令到程序的运行列表,允许多个-e选项 -f [附加命令文件],--file=[附加命令文件] 读取文件的附加命令添加到程序的运行列表 -i[后缀],--in-place[=后缀] 根据附加命令编辑文件并保存,如果存在后缀则以文件名加后缀的形式生成一个备份文件,即有后缀的为原文件,无后缀的为修改后的文件 -c,--copy 当在-i模式下整理文件时,使用复制代替重命名(这里涉及到了文件的inode号) -b,--binary 以二进制模式打开文件,对CR和LFS(变更请求和日志结果文件系统)不进行特殊对待,为兼容WIN32/CYGWIN/MSDOS/EMX -l N,--line-length=N 为附加命令“l”指定所需的换行长度,显示形式为n-1个字符串+\,最后一行没有\。 --posix 禁用所有GNU扩展 -r,--regexp-extended 在附加命令中使用正则表达式 -s,--separate 将文件视为独立文件,而不是单个连续的长文件流 -u,--unbuffered 从输入文件加载最小数量的数据并更频繁地刷新输出缓冲区 -z,--null-data 用NUL字符分隔行
(2).附加命令
: [标签] 为附加命令b和t设置标签 b [标签] 跳转到设置好的标签;如果没有跟随标签则跳到附加命令末尾,结束该行的命令执行 t [标签] 如果s///(替换命令)执行成功,则跳转到设置好的标签;如果没有跟随标签则跳到附加命令末尾,结束该行的命令执行 T [标签] 与t相反,s///没成功时跳转到设置好的标签;如果没有跟随标签则跳到附加命令末尾,结束该行的命令执行 示例:"s/root/xxx/;t a;s/0/1/g;:a"表示如果替换命令执行成功则不执行第二个替换命令; "/^root/b a;s/0/1/g;:a;s/root/xxx/g"表示如果当前行以root开头则不进行第一个替换命令,直接进行第二个替换命令 # [附加命令] 注释,如果存在于附加命令文件则持续到当前行,如果存在于附加命令则持续到该命令结束 {命令块} 将多条附加命令作为一个整体看待 [附加命令1];[附加命令2];... 分号将附加命令进行分隔,允许一次编辑多条附加命令 = 打印行号 a \[文本] 在当前行的下一行添加一行或多行文本,多行时可以使用\n转义字符进行换行 i \[文本] 在当前行的上一行添加一行或多行文本,多行时可以使用\n转义字符进行换行 c \[文本] 将当前行替换为一行或多行文本,多行时可以使用\n转义字符进行换行 示例:"1i \[文本]"表示在第一行的上一行添加文本;"i \[文本]"表示在每行的上一行添加文本 q [退出代码] 立即退出sed命令,$?获取值为设置好的退出代码 Q [退出代码] 立即退出sed命令,$?获取值为设置好的退出代码 注意:q和Q的区别在于,当没有取消自动打印模式空间时,q在退出前会打印当前模式空间,而Q则不会打印当前模式空间 r [文件名] 将文件内容添加到当前行的下一行 R [文件名] 文件内的每一行都作为一个单独的内容,从指定行开始,每读取一行输入文件的内容,在该行下一行添加内容 示例:"1r [文件名]"表示在输入文件的第一行的下一行添加文件所有内容;"r [文件名]"表示在输入文件的每一行的下一行添加文件所有内容; "1R [文件名]"表示在输入文件的第一行的下一行添加文件的第一行内容,即使文件内存在多行也只运行一次; "R [文件名]"表示从输入文件的第一行开始,每行追加文件的对应的一行内容,直到输入文件或文件内容中的一个结束; "2,4R [文件名]"表示从输入文件的第二行到第四行,每行追加文件的第一行到第三行内容的一行内容。 d 删除模式空间 D 与d类似(有差异,但暂时不知道怎么触发) h|H 拷贝或追加模式空间的内容到内存中的缓冲区 g|G 拷贝或追加内存中的缓冲区到模式空间 l 以视觉清晰的效果显示当前行,不会取消默认打印模块,转换符会以$的形式展现 l [长度] 以视觉清晰的效果显示当前行,指定了每次打印的长度,并且转行以\作为连接符(计算在长度内) n|N 将下一行读或追加到模式空间,区别在于读取会覆盖原有内容,追加则不会 p 打印模式空间所有内容 P 打印模式空间内的第一行 s/[查找内容(正则表达式)]/[替换内容]/ 尝试将查找内容与模式空间内的内容匹配,如果成功则替换成功匹配的部分。替换内容可以使用特殊字符&来指代模式空间内的匹配内容, 特殊转义字符\1到\9表示正则表达式中的相应匹配的子表达式。(s/[查找内容]/[替换内容]/g可以替换所有匹配到的内容) w [文件名] 将当前模式空间内容写入到指定文件中,即另存为 W [文件名] 将当前模式空间内的第一行写入指定文件中 x 交换内存中的缓冲区和模式空间的内容
(3).实例
说明:模式空间可以认为是sed命令每次读取文件内容的缓存区,默认一次读取文件一行。
准备两个测试文件
[root@youxi1 ~]# vim readFile root:0:0:root:123456:password abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass [root@youxi1 ~]# vim a.txt 12345 67890
1)查看readFile文件的2到4行
[root@youxi1 ~]# sed -e "2,4p" readFile -n //-e选项是默认选项,可以不写 abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass [root@youxi1 ~]# sed "2,4p" readFile //如果没有-n选项,sed会默认打印模式空间的内容 root:0:0:root:123456:password abc:1:1:abc:password1 abc:1:1:abc:password1 xyz:2:2:abc:password2 xyz:2:2:abc:password2 root:3:4:abc:pass root:3:4:abc:pass
2)-i选项与-c选项,重命名与复制
#没有-c选项时,-i选项是将原文件重命名成备份文件 [root@youxi1 ~]# ls -i readFile //查看readFile的inode号 33575417 readFile [root@youxi1 ~]# sed -i.bak "1,2p" readFile -n //使用-i选项编辑并保存文件 [root@youxi1 ~]# ls -i readFile //可以看到inode号与原文件的inode不同 33574999 readFile [root@youxi1 ~]# cat readFile //内容和原文件也不一样 root:0:0:root:123456:password abc:1:1:abc:password1 [root@youxi1 ~]# ls -i readFile.bak //备份文件的inode号与原文件的inode号相同 33575417 readFile.bak [root@youxi1 ~]# cat readFile.bak //内容和原文件也一样 root:0:0:root:123456:password abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass #当-i选项与-c选项联合使用时 [root@youxi1 ~]# sed -i.cp "1,2p" readFile.bak -n -c [root@youxi1 ~]# ls -i readFile.bak //可以看到inode号和原文件相同 33575417 readFile.bak [root@youxi1 ~]# cat readFile.bak //内容与原文件不一样 root:0:0:root:123456:password abc:1:1:abc:password1 [root@youxi1 ~]# ls -i readFile.bak.cp //备份文件的inode号与原文件的inode号不同 34037099 readFile.bak.cp [root@youxi1 ~]# cat readFile.bak.cp //内容与原文件一样 root:0:0:root:123456:password abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass
3)附加命令a \[文本],i \[文本],c \[文本]
[root@youxi1 ~]# rm -rf readFile readFile.bak [root@youxi1 ~]# mv readFile.bak.cp readFile [root@youxi1 ~]# cat readFile root:0:0:root:123456:password abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass [root@youxi1 ~]# sed "1a \add" readFile //在第一行下方添加 root:0:0:root:123456:password add abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass [root@youxi1 ~]# sed "1i \add" readFile //在第一行上一行添加 add root:0:0:root:123456:password abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass [root@youxi1 ~]# sed "1c \add" readFile //替换第一行 add abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass [root@youxi1 ~]# sed "1c \add\nabc\t123 456" readFile //换行的转义字符\n,Tab的转义字符\t add abc 123 456 abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass
4)附加命令=,打印行号
[root@youxi1 ~]# sed "=" readFile 1 root:0:0:root:123456:password 2 abc:1:1:abc:password1 3 xyz:2:2:abc:password2 4 root:3:4:abc:pass
5)附加命令d
[root@youxi1 ~]# sed "1,2d" readFile xyz:2:2:abc:password2 root:3:4:abc:pass
6)附加命令s/[查找内容]/[替换内容]/(g)
[root@youxi1 ~]# sed "s/root/xxx/" readFile //替换匹配到的第一个 xxx:0:0:root:123456:password abc:1:1:abc:password1 xyz:2:2:abc:password2 xxx:3:4:abc:pass [root@youxi1 ~]# sed "s/root/xxx/g" readFile //替换匹配到的所有 xxx:0:0:xxx:123456:password abc:1:1:abc:password1 xyz:2:2:abc:password2 xxx:3:4:abc:pass [root@youxi1 ~]# sed "s/a.*p/1234/" readFile //正则匹配内容并进行替换 root:0:0:root:123456:password 1234assword1 xyz:2:2:1234assword2 root:3:4:1234ass [root@youxi1 ~]# sed "s/a.*p/&1234/" readFile //正则匹配内容,保留原有的基础上进行替换 root:0:0:root:123456:password abc:1:1:abc:p1234assword1 xyz:2:2:abc:p1234assword2 root:3:4:abc:p1234ass
一样可以在s前加数字表示从第几行开始查找。
7)-r选项,使用正则表达式匹配指定行
[root@youxi1 ~]# sed -r "/^root/i \1234" readFile //找到指定的行,在它的上一行添加内容 1234 root:0:0:root:123456:password abc:1:1:abc:password1 xyz:2:2:abc:password2 1234 root:3:4:abc:pass [root@youxi1 ~]# sed "/^.*abc/{s/^.*$/&\tName/}" readFile //可以省略-r选项 root:0:0:root:123456:password abc:1:1:abc:password1 Name xyz:2:2:abc:password2 Name root:3:4:abc:pass Name [root@youxi1 ~]# sed "/^.*abc/s/^.*$/&\tName/" readFile //就连{}也可以省略,但不建议这样写,因为不方便理解 root:0:0:root:123456:password abc:1:1:abc:password1 Name xyz:2:2:abc:password2 Name root:3:4:abc:pass Name
8)附加命令q、Q
[root@youxi1 ~]# sed "/^.*abc/q" readFile root:0:0:root:123456:password abc:1:1:abc:password1 [root@youxi1 ~]# sed "/^.*abc/Q" readFile root:0:0:root:123456:password
9)附加命令r [文件名]、R [文件名]
[root@youxi1 ~]# sed "/^root/r a.txt" readFile root:0:0:root:123456:password 12345 67890 abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass 12345 67890 [root@youxi1 ~]# sed "/^root/R a.txt" readFile root:0:0:root:123456:password 12345 abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass 67890
10)附加命令n、N、p、P、w、W
首先一定要了解n(读取下一行到模式空间)、N(追加下一行到模式空间),以及默认打印模式空间的触发动作(预备读取下一行,结束sed命令)。注意:读取和追加到模式空间的行,sed命令就不再读取了。
[root@youxi1 ~]# sed "n;p" readFile root:0:0:root:123456:password //预备执行附加命令n,触发默认打印当前模式空间。n执行完成后,模式空间内容是第二行内容 abc:1:1:abc:password1 //执行附加命令p,打印当前模式空间,模式空间内容不变 abc:1:1:abc:password1 //sed命令预备读取下一行,触发默认打印当前模式空间。读取下一行完成后,模式空间内容是第三行 xyz:2:2:abc:password2 //预备执行附加命令n,触发默认打印当前模式空间。n执行完成后,模式空间内容是第四行 root:3:4:abc:pass //执行附加命令p,打印当前模式空间,模式空间内容不变 root:3:4:abc:pass //sed命令结束,打印当前模式空间(此举是清空模式空间?) [root@youxi1 ~]# sed "N;p" readFile root:0:0:root:123456:password abc:1:1:abc:password1 //执行附加命令N,模式空间内容为第一行和第二行;执行附加命令p,打印当前模式空间 root:0:0:root:123456:password abc:1:1:abc:password1 //sed命令预备读取下一行,触发默认打印当前模式空间。读取下一行完成后,模式空间内容是第三行 xyz:2:2:abc:password2 root:3:4:abc:pass //执行附加命令N,模式空间内容由第三行变为第三第四行;执行附加命令p,打印当前模式空间 xyz:2:2:abc:password2 root:3:4:abc:pass //sed命令结束,打印当前模式空间(此举是清空模式空间?)
接着了解p(打印当前模式空间)和P(打印模式空间内的第一行)。在了解n和N的情况下,还是很好理解的。
[root@youxi1 ~]# sed "N;p" readFile -n root:0:0:root:123456:password abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass [root@youxi1 ~]# sed "N;P" readFile -n root:0:0:root:123456:password xyz:2:2:abc:password2
最后是w(保存当前模式空间到指定文件)和W(保存当前模式空间内的第一行到指定文件),和p、P的区别就是不打印,直接保存到文件中。了解了p和P,那么这两个也是很简单的。
[root@youxi1 ~]# sed "N;w b.txt" readFile -n [root@youxi1 ~]# sed "N;W c.txt" readFile -n [root@youxi1 ~]# cat b.txt root:0:0:root:123456:password abc:1:1:abc:password1 xyz:2:2:abc:password2 root:3:4:abc:pass [root@youxi1 ~]# cat c.txt root:0:0:root:123456:password xyz:2:2:abc:password2
(4).sed增删改查
sed命令比较常用的就是增删改查四项,“增”可以使用附加命令a \[文本]、i \[文本]、r [文件名]和R [文件名],“删”可以使用附加命令d,“改”可以使用附加命令c \[文本]和s/[查找内容]/[替换内容]/,“查”可以使用-r选项以及附加命令p。