一天一命令-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的主要内容,如果未能解决你的问题,请参考以下文章

一天一命令-ls

一天一命令-history

一天一命令-xargs

一天一命令-crontab

一天一命令-screen

一天一点MySQL复习——存储过程