shell脚本中sed的使⽤
Shell脚本之sed篇
原创作品,允许转载,转载时请务必以超链接形式标明⽂章、作者信息和本声明。否则将追究法律责任。
⽬录:
⼀、概述
⼆、sed基本语法格式
三、简单正则表达式
四、sed脚本指令(注释、替换、删除、追加、打印、下⼀⾏、读写⽂件、退出、多⾏模式)
五、综合案例
⼀、概述
1.sed是⼀款流编辑⼯具,⽤来对⽂本进⾏过滤与替换⼯作,特别是当你想要对⼏⼗个配置⽂件做统计修改时,你会感受到sed的魅⼒! sed通过输⼊读取⽂件内容,但⼀次仅读取⼀⾏内容进⾏某些指令处理后输出,所以sed更适合于处理⼤数据⽂件。
2.sed流程:
* 通过⽂件或管道读取⽂件内容。
* sed并不直接修改源⽂件,⽽是将读⼊的内容复制到缓冲区中,我们称之为模式空间(pattern space)。
* 根据sed的指令对模式空间中的内容进⾏处理并输出结果,默认输出⾄标准输出即屏幕上。
输⼊
------------------------------------------------
|
|
v
v
读取⼀⾏内容,并复制到模式空间 <------------ sed 指令
|
|
v
v
------------------------------------------------
输出经过处理后的内容
*****************************************************************************************************
⼆、sed基本语法结构
sed [script] []
sed 选项... [脚本指令] [输⼊⽂件]
如果没有输⼊⽂件,则sed默认对标准输⼊进⾏处理(即键盘输⼊)。脚本指令是第⼀个不以“-”开始的参数。
1.选项含义:
--version 显⽰sed版本。
--help 显⽰帮助⽂档。
-n,--quiet,--silent 静默输出,默认情况下,sed程序在所有的脚本指令执⾏完毕后,将⾃动打印
模式空间中的内容,这些选项可以屏蔽⾃动打印。
-e script 允许多个脚本指令被执⾏。
-f script-file,
--file=script-file 从⽂件中读取脚本指令,对编写⾃动脚本程序来说很棒!
-i,--in-place 直接修改源⽂件,经过脚本指令处理后的内容将被输出⾄源⽂件(源⽂件被修改)
慎⽤!
-l N, --line-length=N 该选项指定l指令可以输出的⾏长度,l指令⽤于输出⾮打印字符。
--posix 禁⽤GNU sed扩展功能。
-r, --regexp-extended
在脚本指令中使⽤扩展正则表达式
-s, --separate 默认情况下,sed将把命令⾏指定的多个⽂件名作为⼀个长的连续的输⼊流。
⽽GNU sed则允许把他们当作单独的⽂件,
这样如正则表达式则不进⾏跨⽂件匹配。
-u, --unbuffered 最低限度的缓存输⼊与输出。
2.简单案例:
以上仅是sed程序本⾝的选项功能说明,⾄于具体的脚本指令(即对⽂件内容做的操作)后⾯我们会详细描述,
这⾥就简单介绍⼏个脚本指令操作作为sed程序的例⼦。
a,append 追加
i,insert 插⼊
d,delete 删除
s,substitution 替换
案例说明:灰⾊背景的内容为待处理的源⽂件,红⾊字体的⽂字为sed脚本,蓝⾊字体的⽂字为处理后的结果输出。
这⾥为样本⽂件:
[jacob@localhost ~] #cat
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.0.1
NETMASK=255.255.255.0
GATEWAY=192.168.0.254
[jacob@localhost ~] #sed '2a TYPE=Ethernet' 第⼆⾏后添加TYPE=Ethernet
[jacob@localhost ~] #sed '3i TYPE=Ethernet' 第三⾏前添加TYPE=Ethernet
[jacob@localhost ~] #sed 's/yes/no/g' 将样本⽂件中的所有yes替换为no
[jacob@localhost ~] #sed '3,4d' 删除第3⾄4⾏的内容
以上⼤多数操作指令,都依据⾏号定位操作对象(地址),如:2a即第⼆⾏后添加。
但实际情况可能⼤多数情况你并不确定你要操作对象(地址)的⾏号,这时更多的我们会使⽤正则表达式确定操作对象(地址)。下⾯是使⽤正则表达式定位操作⾏的⽰例:
[jacob@localhost ~] #sed '/ONBOOT/a TYPE=Ethernet'
匹配到包含ONBOOT的⾏,并在其后添加TYPE=Ethernet
[jacob@localhost ~] #sed '/^GATEWAY/d'
匹配以GATEWAY开始的⾏,并删除改⾏
另外我们的操作指令可以,写⼊到脚本⽂件中并通过sed的-f选项读取。
创建⼀个sed脚本,内容如下:
[jacob@localhost ~] #cat sed.sh
/^$/d 这条指令的作⽤是:匹配到空⽩⾏后,删除改⾏。
[jacob@localhost ~] #sed -f sed.sh 对⽂件执⾏sed.sh指令
另外,当你需要执⾏多个指令时,可以使⽤以下三种⽅法:
1. [jacob@localhost ~] #sed 's/yes/no/;s/static/dhcp/' 注:使⽤分号隔开指令。
2. [jacob@localhost ~] #sed -e 's/yes/no/' -e 's/static/dhcp/' 注:使⽤-e选项。
3. [jacob@localhost ~] #sed '
>s/yes/no/
>s/static/dhcp/' 注:利⽤分⾏指令。
然⽽在命令⾏上输⼊过长的指令是愚蠢的,这时就需要-f选项指定sed脚本⽂件,在脚本⽂件中可以包含多⾏指令,⽽且便于修改!
*****************************************************************************************
三、简单正则表达式
从以上案例中我们不难发现,我们编写的脚本指令需要指定⼀个地址来决定操作范围,如果不指定则默认对⽂件的所有⾏操作。如:sed 'd' 将删除的所有⾏,⽽'2d'则仅删除第⼆⾏。
1.为sed指令确定操作地址:
number 指定输⼊⽂件的唯⼀⾏号。
first~step 以first开始,并指定操作步长为step,如1~2,指定第⼀⾏,第三⾏,第五⾏... 为操作地址。
[jacob@localhost ~] #sed -n '1~2p' 打印⽂件的奇数⾏。
2~5,则可以指定第⼆⾏开始,每5⾏匹配⼀次操作地址。
$ 匹配⽂件的最后⼀⾏。
/regexp/ //中间包含的是正则表达式,通过正则表达式匹配操作地址。
注://空的正则表达式,匹配最近⼀次正则表达式的匹配地址,会在后⾯使⽤看出效果。
\cregexpc 匹配扩展正则表达式,c字符可以使⽤任意字符替代。
addr1,addr2 匹配从操作地址1到操作地址2的所有⾏。
[jacob@localhost ~] #sed '2,8d' 删除2⾄8中间的所有⾏。
addr1,+N 匹配地址1以及后⾯的N⾏内容。
2.正则表达式概述(对你要内容的⼀种描述)
char 字符本⾝就匹配字符本⾝,如/abc/就是定位包含abc的⾏。
* 匹配前⾯表达式出现了0或若⼲次,如/a*/可以帮你到a,aa,aaa,... ...等等。
\+ 类似于*,但匹配前⾯表达式的1次或多次,这属于扩展正则表达式。
\? 类似于*,但匹配前⾯表达式的0次或1次,这属于扩展正则表达式。
\{i\} 类似于*,但匹配前⾯表达式的i次(i为整数),如:a\{3\}可以帮你到aaa。
\{i,j\} 匹配前⾯表达式的i到j次,如a\{1,2\}可以帮你到a或aa或aaa。
\{i,\} 匹配前⾯表达式⾄少i次。
\( \) 将\( \)内的模式存储在保留空间。最多可以存储9个独⽴⼦模式,可
通过转义\1⾄\9重复保留空间的内容⾄此点。
\n 转义\1⾄\9重复保留空间的内容⾄此点。
例:的内容为ssttss
grep '\(ss\)tt\1' \1表⽰将ss重复在tt后⾯
该grep命令等同于grep ssttss 在⽂件中ssttss
. (点)匹配任意字符。
^ 匹配⾏的开始,如^test 将匹配所有以test开始的⾏。
$ 匹配⾏的结尾,如test$ 将匹配所有以test结尾的⾏。
[] 匹配括号中的任意单个字符,如a[nt] 将匹配an或at。
[^] 匹配不包含在[]中的字符,如[^a-z] 将匹配除a-z以外的字符。
\n 匹配换⾏符。
\char 转义特殊字符,如\*,就是匹配字⾯意义上的星号。
**************************************************************************************
四、sed脚本指令
常⽤的sed脚本指令有:
*注释(#)
*替换(s)
*删除(d)
*追加(a)
*插⼊(i)
*更改(c)
*列印(l)
*转换(y)
*打印(p)
*读写⽂件(r,w)
*退出(q)
*下⼀步(n)
*Next(N)
*Print(P)
*Delete(D)
*Hold(h,H)
*Get(g,G)
*branch,test
sed脚本指令的基本格式:
[address]command
[地址]命令备注:有些命令仅可以对⼀⾏操作,有些可以对多⾏操作。
命令可以⽤⼤括号进⾏组合以使命令序列可以作⽤于同⼀个地址:
address{
command1
command2
command3
}
第⼀个命令可以和左⼤括号在同⼀⾏,但右⼤括号必须单独处于⼀⾏。
注意事项:命令后添加空格会产⽣错误。
1.注释(#):
注释⾏是以#开始的⾏,如果#后⾯的字符为n,则屏蔽sed程序的⾃动输出功能,等同于命令选项-n。
2.替换(s,Substitution):
[address]s/pattern/replacement/flags
address为操作地址,s为替换指令,/pattern/匹配要替换的内容,/replacement/为替换的内容。
flags可以是:
n 1⾄512之间的数字,表⽰对模式空中指定模式的第n次出现进⾏替换。
如⼀⾏中有3个A,⽽只想替换第⼆个A。
g 对模式空间的匹配进⾏全局更改。没有g则仅第⼀次匹配被替换,如⼀⾏中有3个A,则仅替换第⼀个A。 p 打印模式空间的内容。
w file
将模式空间的内容写到⽂件file中。
replacement为字符串,⽤来替换与正则表达式匹配的内容。
在replacement部分,只有下列字符有特殊含义:
& ⽤正则表达式匹配的内容进⾏替换。
\n 匹配第n个⼦串,这个⼦串之前在pattern中⽤\( \)指定。
\ 转义(转义替换部分包含的:&, \等)。
-----------------------------------------------------------------------------------------------
⽰例1所使⽤的样本⽂件为:
[jacob@localhost ~] #cat
<html>
<title>First Web</title>
<body>Hello the World! <body>
</html>
⽰例1:将样本⽂件中的第⼆个<body>替换为</body>
编写sed脚本为:
[jacob@localhost ~] #cat sed.sh
/body/{
s//\/body/2 注:替换与⾏匹配相同的内容即body,替换为/body,但仅替换第⼆个body为/body。
}
执⾏sed程序的结果:
[jacob@localhost ~] #sed -f sed.sh
<html>
<title>First Web</title>
<body>Hello the World!</body>
</html>
---------------------------------------------------------------------------------------------
⽰例2所使⽤的样本⽂件为:
[jacob@localhost ~] #cat
<html>
<title>First Web</title>
<body>
h1Helloh1
h2Helloh2
h3Helloh3
</body>
</html>
⽰例2:给所有第⼀个的h1,h2等添加<>;第⼆个h1,h2添加</>
编写sed脚本为:
[jacob@localhost ~] #cat sed.sh
/h[0-9]/{ 注:匹配h紧跟⼀个数字的⾏
s//\<&\>/1 注:替换与上⼀⾏中匹配内容相同的内容,即替换h[0-9],替换为<&>,其中&即前⾯要替换的内容。s//\<\/&\>/2 注:上⼀条指令仅替换第⼀个,本⾏指令⽤来替换第⼆个。
}
shell最简单脚本执⾏sed程序的结果:
[jacob@localhost ~] #sed -f sed.sh
<h1>Hello</h1>
<h2>Hello</h2>
<h3>Hello</h3>
---------------------------------------------------------------------------------------------
技巧:关于 's///' 命令的另⼀个妙处是 '/' 分隔符有许多替换选项。
如果规则表达式或替换字符串中有许多斜杠,则可以通过在 's' 之后指定⼀个不同的字符来更改分隔符。
⽰例:$ sed -e 's:/usr/local:/usr:g' 这⾥:为分隔符。
3.删除(d ,delete):
删除指令删除匹配的⾏,⽽且删除命令还会改变sed脚本中命令的执⾏顺序。因为:
匹配的⾏⼀旦被删除,模式空间将变为“空”,⾃然不会再执⾏sed脚本后续的命令。
删除命令将导致读取新的输⼊⾏(下⼀⾏),⽽sed脚本中的命令则从头开始执⾏。
注意事项:删除将删除整个⾏,⽽不只是删除匹配的内容。(如要删除匹配的内容,可以使⽤替换)
⽰例1所使⽤的样本⽂件为:
[jacob@localhost ~] #cat
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.0.1
NETMASK=255.255.255.0
GATEWAY=192.168.0.254
⽰例1:删除⽂件中的空⽩⾏
编写sed脚本为:
[jacob@localhost ~] #cat sed.sh
/.*/{
/^$/d
}
执⾏sed程序的结果:
[jacob@localhost ~] #sed -f sed.sh
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.0.1
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论