一天一命令-sed
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一天一命令-sed相关的知识,希望对你有一定的参考价值。
一天一命令-sed
sed - stream editor for filtering and transforming text
sed 4.2.2
sed是一种流编辑器,读取一行,处理一行,输出一行。sed先读取文件中的一行内容存储到被称为模式空间(pattern space)的临时缓冲区中,接着根据设定的条件来处理缓冲区中的内容,多个条件则多次处理,处理完成后,输出到屏幕,接着读取和处理下一行。源文件内容并没有改变,除非使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对多个文件执行相同的编辑处理工作;编写转换程序。
【重要】sed处理的是缓冲区的行数据,不影响源数据,一次读取,可以多次处理,后续的编辑命令都是应用前面命令编辑后输出的结果,所以一定要注意编辑命令的顺序问题。sed的处理顺序,先读取文件中的一行数据保存到缓冲区,再查看地址位置是否匹配,匹配则执行命令,是先匹配起始地址,匹配则执行编辑命令,不匹配则继续查看下一个地址位置或继续读取下一行。
Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]... OPTION: -n 仅显示经过sed处理后的行数据,通常配合-p使用,即打印匹配行,相当于grep -e 多次编辑,支持多个条件匹配和处理,顺序执行,注意多次处理指的是处理缓冲区中读取的行数据,而不是源文件的行数据,即一次读取,多次处理。 -f 从指定的文件中读取编辑脚本 -i+后缀名 指定后缀名并先备份源文件,再编辑源文件;不加后缀名表示直接编辑源文件 -r 使用扩展的正则表达式
-e的理解如下,其实等同于cmd1;cmd2;...
#more f1
a
b
c
d
#sed -n -e ‘1,3p‘ -e ‘2anewline‘ -e ‘2d‘ f1 //先读取第一行到缓冲区,并依次匹配三个条件进行处理,处理一次输出一次
a //读取第一行,匹配第一个条件,执行打印输出,不匹配后两个条件,则第一行处理结束
b //读取第二行,匹配第一个条件,执行打印输出
newline //继续匹配第二个条件,即在匹配行的下一行添加newline行,继续匹配第三个条件,删除第二行数据,注意这里删除的是缓冲区中的数据
c //读取第三行,匹配第一个条件,打印输出,不匹配后两个条件,则第三行处理结束
#sed -n -e ‘2d‘ -e ‘1,3p‘ -e ‘2abc‘ f1
a //读取第一行内容,不匹配第一个条件,不处理,匹配第二个条件,打印输出,不匹配第三个条件,不处理,第一行处理结束
c //读取第二行内容,匹配第一个条件,删除处理,匹配后续两个条件,但缓冲区内容已被删除,所以输出为空,即最后不显示第二行。读取第三行,匹配第二个条件,打印输出。
地址定界:
(1)不给地址:对全文进行处理
(2)单地址:
#: 指定行
/pattern/ :被指定模式匹配到的每一行
(3)地址范围:
#,#
#,+#
#,/pat1/
/pat1/,/pat2/
(4) ~ :步进
1~2 奇数行
2~2 偶数行
元字符集
^ 锚定行的开始,如/^sed/匹配所有以sed开头的行。
$ 锚定行的结束,如/sed$/匹配所有以sed结尾的行。
. 匹配一个非换行符的字符,如/s.d/匹配s后接一个任意字符,然后是d。
* 匹配零个或多个字符,如/*sed/匹配任何一个或多个字符后跟sed的行。
[] 匹配一个指定范围内的字符,如/[Ss]ed/匹配sed和Sed。
[^] 匹配一个不在指定范围内的字符,如/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。
\(..\) 保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。
& 保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。
\< 锚定单词的开始,如/\<love/匹配包含以love开头的单词的行。
\> 锚定单词的结束,如/love\>/匹配包含以love结尾的单词的行。
x\{m\} 重复字符x,m次,如/o\{5\}/匹配包含5个o的行。
x\{m,\} 重复字符x,至少m次,如/o\{5,\}/匹配至少有5个o的行。
x\{m,n\} 重复字符x,至少m次,不多于n次,如/o\{5,10\}/匹配5--10个o的行。
Sed 命令地址匹配问题总结——转载于http://kodango.com
0,addr2和1,addr2这两种写法一般情况下是相同的,但是有不同的情况
seq 6 | sed -n ‘0,/1/p‘ //打印第一行,/1/是正则,因为第一行的内容就是1,0表示默认匹配第一行
seq 6 | sed -n ‘1,/1/p‘ //打印所有内容,why?
为什么不相同呢? 解释如下:
0, addr2 这种形式默认第一个地址是匹配的,然后直到add2匹配为止。因此上述情况,只要看每一行是否匹配第二个地址addr2就可以了,因为第一行是匹配的,所以打印到第一行为止。
1, addr2 这种形式就是普通形式,不管addr2匹配与否,第一行是匹配的,然后读入第二行,发现不匹配addr2,继续读,直到最后也没找到匹配,因此打印从第1行到最后一行之间的所有内容。
地址范围addr1, addr2的匹配方式,从匹配addr1的那行开始,打开匹配开关,直到匹配addr2的那行结束,关闭匹配开关,之后的行会忽略这个地址范围,不再做匹配。
如果addr1是行号,新读入行的行号大于addr1,则匹配;小于addr1,则不匹配。
如果addr2是行号,新读入行的行号小于addr2,则匹配,继续往下读;大于addr2,则不匹配,关闭匹配开关。
$ seq 6 | sed ‘1,2d‘ | sed ‘1,2d‘ //结果返回5 6
$ seq 6 | sed -e ‘1,2d‘ -e ‘1,2d‘ //结果返回4 5 6
显然这两种情况使用sed的命令形式是不一样的,第一种利用管道使用了sed两次,结果返回5 6,没什么问题;第二种情况在同一个sed命令中使用了两次1,2d,按常理应该是返回 3 4 5 6,结果返回 4 5 6,第3行竟然也被意外地删除了,为什么呢?第二条命令解释:
1.首先第一行被读入,遇到第一组expression -> 1,2d,第一行匹配成功(打开匹配开关),执行d命令,d命令清空模式空间的内容,因此不会再执行接下来的命令。
2.继续从标准输入读入第二行,同1
3.读入第三行,第一组expression匹配失败(因为3>2),因此试着执行第二组expersson->1,2d,因为3>1,打开匹配开关,执行d。(这里是关键)
4.读入第四行,执行第二组expersson->1,2d,因为4>2,匹配失败,关闭匹配开关,同时也不执行d。
5.因此,最后第1 2 3行被删除。
编辑命令
a\ 在当前行下面插入一行文本,支持使用 \n 实现多行追加。
i\ 在当前行上面插入一行文本。
c\ 把选定的行改为新的文本。
d 删除模式空间匹配的行。
D 删除模式空间的第一行。删除当前模式空间开端至 \n 的内容(不再传至标准输出),放弃之后的命令,但是对剩余模式空间重新执行sed
s 替换指定字符 s/a/string,只有a的位置才支持正则表达式,后边替换的只能是字符串。
h 把模式空间中的内容覆盖到内存中的缓冲区。
H 把模式空间中的内容追加到内存中的缓冲区。
g 读取内存缓冲区的内容覆盖到模式空间中的内容。
G 读取内存缓冲区的内容追加到模式空间中的内容。
l 列表显示不能打印的字符清单。
n 读取匹配到的行的下一行覆盖至模式空间。
N 读取匹配到的行的下一行追加至模式空间。
p 显示模式空间中的内容。
P (大写) 打印模式空间的第一行。
q 退出Sed。
b lable 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。
r file 从file中读行。
t label if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
T label 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
w file 保存模式匹配的行至指定文件。
W file 读取指定文件的文本至模式空间中匹配到的行后。
! 模式空间中匹配行取反处理。
= 打印当前行号。
# 把注释扩展到下一个换行符以前。
替换
s/// 查找替换,支持使用其它分隔符,[email protected]@@,s###
替换标记:
g 行内全局替换
p 显示替换成功的行
w /PATH/TO/SOMEFILE 将替换成功的行保存至文件中
\1 组匹配标记
& 匹配字符串标记
案例:
sed ‘‘ f1 //显示文件内容,相当于cat sed -n ‘‘ f1 sed ‘2p‘ /etc/passwd sed -n ‘2p‘ /etc/passwd //只显示匹配到的行 sed -n ‘1,3p‘ /etc/passwd sed -n ‘/root/p‘ /etc/passwd sed -n ‘2,/root/p‘ /etc/passwd sed ‘/root/a\superman‘ /etc/passwd //在匹配到root的行的下一行插入superman sed ‘/root/i\superman‘ /etc/passwd //上一行 sed ‘/root/c\superman‘ /etc/passwd //替换匹配到的行 sed ‘1,3wa‘ f1 //匹配f1文件的1-3行并保存到a文件中 sed -n ‘/^$/=‘ f1 //显示空行行号,但是不会显示tab空行的行号 sed ‘/^$/d‘ f1 //删除空行,但是不会删除tab空行 sed ‘1,5d‘ f1 sed ‘2,$d‘ f1 //删除从第二行到末尾的所有行 sed ‘$d‘ f1 //删除空白行 sed ‘/^root/d‘ passwd //删除以root开头的行 nl passwd | sed ‘2,10d‘ nl passwd | sed -n ‘/root/p‘ sed ‘s/root/admin/g‘ passwd sed -n ‘s/a/d/p‘ f1 //仅显示替换的行 sed -n ‘s/root/&superman/p‘ passwd sed -n ‘s/root/superman&/p‘ passwd echo aaaaaa | sed ‘s/a/A/g‘ //全局替换 echo aaaaaa | sed ‘s/a/A/2‘ //表示只替换第二个匹配项,显示为aAaaaa echo aaaaaa | sed ‘s/a/A/2g‘ //从第二个匹配到的开始替换 echo aaaaaa | sed ‘s/a/A/3g‘ //第三个,显示结果为aaAAAA,第n个,就是ng echo this is a test line | sed ‘s/\w\+/[&]/g‘ //正则表达式\w\+表示匹配每一个单词,&表示匹配到单词,显示结果为[this] [is] [a] [test] [line] sed -i.bak ‘2d‘ f1 //编辑前先备份文件f1为f1.bak,然后编辑f1文件 sed -n ‘p;n‘ f1 //显示奇数行 sed -n ‘n;p‘ f1 //显示偶数行 sed -n ‘1~2p‘ f1 //奇数行 sed -n ‘2~2p‘ f1 //偶数行 sed ‘n;d‘ f1 //显示奇数行 sed ‘1!G;h;$!d‘ f1 //倒序显示 sed -n ‘1!G;h;$p‘ f1 //倒序 sed ‘N;D‘ f1 //显示最后一行 sed ‘$!N;$!D‘ f1 //显示最后两行 sed ‘$!d‘ f1 //删除除了最后一行的行,即保留最后一行 sed ‘G‘ f1 //为每一行增加一个空行 sed ‘g‘ f1 //清空文件 seq 10 | sed -n ‘N;pa----‘ //按照每两行数据为分隔并显示,即将多行分隔为两行两行显示 seq 10 | sed -n ‘N;P‘ //只打印最后一行 sed ‘/^S/d;G‘ f1 sed ‘3q‘ f1 name=root;sed -n "/$name/p" passwd //匹配变量需要使用双引号"" nl passwd | sed -n ‘/root/{s/bash/shell/;p}‘ //表示找到root行,执行后面花括号的一组命令,每个命令之间用分号隔开 sed ‘s/^/# /‘ f1 //在每行的开头添加#号 sed -i ‘/IPADDR/[email protected]\[email protected]@‘ test //匹配IPADDR的行,把10.1替换成10.12,符号.需要转义 sed -n ‘$=‘ f1 //统计行数,相当于wc -l sed ‘s/^[ \t]*//‘ 删除每一行开头的空白(空格,TAB)左对齐排列全文 sed ‘s/[ \t]*$//‘ 删除每一行最后的空白(空格,TAB) sed ‘/a/{s//&b/;s/^/+ /}‘ f1 //在a后面增加b,同时在被修改的行前面增加+号 sed -e ‘1,3p‘ -e ‘2d‘ f1 //-e可以省略,此命令可以简写为sed ‘1,3p;2d‘ f1 删除空白行和#开头的行 sed -e ‘/^#/d‘ -e ‘/^[[:space:]]*$/d‘ /etc/fstab 取基名和目录名 echo "/etc/sysconfig/network-scripts" |sed -r ‘[email protected](^/.*/)([^/]+/?)@\[email protected]‘ echo "/etc/sysconfig/network-scripts" |sed -r ‘[email protected](^/.*/)([^/]+/?)@\[email protected]‘ 取ifconfig eth0中本机IP ifconfig eth0|sed -n -e ‘2s/^.*r://‘ -e ‘2s/ .*//p‘ /sbin/ifconfig eth0 | grep ‘inet addr‘ | sed ‘s/^.*addr://g‘ | sed ‘s/Bcast.*$//g‘
本文出自 “rackie” 博客,请务必保留此出处http://rackie386.blog.51cto.com/11279229/1941606
以上是关于一天一命令-sed的主要内容,如果未能解决你的问题,请参考以下文章