码迷,mamicode.com
首页 > 其他好文 > 详细

shell文本过滤编程(九):sed命令

时间:2014-08-29 16:09:38      阅读:342      评论:0      收藏:0      [点我收藏+]

标签:脚本   正则表达式   sed   awk   

【版权声明:转载请保留出处:blog.csdn.net/gentleliu。Mail:shallnew at 163 dot com】
sed和awk类似,是很重要的文本过滤工具。
调用sed和调用awk一样,有三种方式:
1. 在命令行键入命令;
2.将sed命令插入脚本文件,然后调用sed;
3. 将sed命令插入脚本文件,并使sed脚本可执行。
使用sed命令行格式为:                
sed [option] ‘sed cmd’ inputfile
使用sed脚本文件,格式为:
sed [option] -f sed_script_file.sed inputfile
无论何种方式,如果sed没有指定输入文件,sed从标准输入中接受输入,一般是键盘或重定向结果。使用sed无论命令是什么,sed并不与初始化文件打交道,它操作的只是一个拷贝,然后所有的改动如果没有重定向到一个文件,将输出到屏幕。
sed选项如下:
-e进行多项编辑,即对输入行应用多条sed命令时使用
-n取消默认的输出
-f指定sed脚本的文件名

Sed有如下命令:
p 打印匹配行
= 显示文件行号
a \ 在定位行号后附加新文本信息
i \ 在定位行号后插入新文本信息
d 删除定位行
c \ 用新文本替换定位文本
s 使用替换模式替换相应模式
r 从另一个文件中读文本
w 写文本到一个文件
q 第一个模式匹配完成后推出或立即推出
l 显示与八进制 A S C I I代码等价的控制字符
{ } 在定位行执行的命令组
n 从另一个文件中读文本下一行,并附加在下一行
g 将模式2粘贴到/pattern n/
y 传送字符
n 延续到下一输入行;允许跨行的模式匹配语句
下面来讲一下sed的各种命令。本系列关于sed的示例使用以下文本文件:
#cat passwd
root:x:0:0:root:/root:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
#
1.    p命令
1)    使用P命令打印文件内容。
#sed 'p' passwd
root:x:0:0:root:/root:/bin/sh
root:x:0:0:root:/root:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
#
发现每一行打印了两次,我们使用-n选项关闭默认的输出:
#sed -n 'p' passwd
root:x:0:0:root:/root:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
# awk实现对比:
#awk '{print}' passwd
root:x:0:0:root:/root:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
#
使用sed不一定要打印所有行出来,我们可以定位到某一行对其进行操作,使用s e d在文件中定位文本的方式:
x                         x为一行号,如 1
x,y                         表示行号范围从x到y,如2,5表示从第2行到第5行
/pattern/                     查询包含模式的行。例如 / d i s k /或/[a-z]/
/pattern /pattern /             查询包含两个模式的行。例如 / d i s k / d i s k s /
pattern/ , x                 在给定行号上查询包含模式的行。如 / r i b b o n / , 3
x , /pattern/                 通过行号和模式查询匹配行。 3 . / v d u /
x,y!                        查询不包含指定行号 x和y的行。1 , 2 !
2)    打印第3行:
#sed -n '3p' passwd
operator:x:37:37:Operator:/var:/bin/sh
#
awk实现对比:
#awk '{if(NR==3)print}' passwd
operator:x:37:37:Operator:/var:/bin/sh
#
3)    打印2到4行:
#sed -n '2,4p' passwd
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
#
awk实现对比:
#awk '{if(NR<=4 && NR>=2)print}' passwd
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
#
4)    打印匹配行
#sed -n '/var/p' passwd
operator:x:37:37:Operator:/var:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
# 
awk实现对比:
#awk '/var/{print}' passwd
operator:x:37:37:Operator:/var:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
#
5)    打印最后一行
#sed -n '$p' passwd
sshd:x:103:99:Operator:/var:/bin/sh

2.    “=”命令,打印行号
#sed -n '/var/=' passwd
3
6
awk实现对比:
#awk '/var/{print NR}' passwd
3
6
如果打印行号及匹配行,必须使用两个sed命令,并使用 e选项。第一个命令打印模式匹配行,第二个使用 =选项打印行号,格式为 sed -n -e /pattern/p -e /pattern/=。
#sed -n -e '/var/p' -e '/var/=' passwd
operator:x:37:37:Operator:/var:/bin/sh
3
sshd:x:103:99:Operator:/var:/bin/sh
6
#
#awk '/var/{print $0 "\n" NR}' passwd
operator:x:37:37:Operator:/var:/bin/sh
3
sshd:x:103:99:Operator:/var:/bin/sh
6
#
3.    \a命令,在指定行后附加新文本
使用符号a \,可以将指定文本一行或多行附加到指定行后面。文本附加操作时,结果输出在标准输出上。要想在附加操作后编辑文本,必须保存文件,然后运行另一个 s e d 命令编辑它。这时文件的内容又被移至缓冲区。
#sed '/root/a\this line is add by sed\haha' passwd
root:x:0:0:root:/root:/bin/sh
this line is add by sedhaha
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
#
#awk '{print;if(/root/)print"this line is add by awk"}' passwd
root:x:0:0:root:/root:/bin/sh
this line is add by awk
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
#
4.    i\命令,和\a命令类似,只是插入文本在匹配行前一行
5.    \c命令,修改指定行
#sed '/root/c\this line is modify by sed\h' passwd
this line is modify by sedh
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
#awk '{if(/root/){print"this line is modify by awk"}else {print}}' passwd
this line is modify by awk
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
#
6.    d命令,删除匹配行
#sed '1,4d' passwd
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
#

#awk '{if(NR>4)print}' passwd
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
#
7.    s命令,替换行文本
格式为:[address [,address]] s/ pattern-to-find /replacement-pattern/[g p w n]
该命令在指定行([address [,address]]),使用S命令,将符合模式pattern-to-find的文本替换为文本replacement-pattern,p选项将打印出替换的行,g选项替换全局所有出现模式,缺省情况下只替换第一次出现模式。w  文件名 使用此选项将输出定向到一个文件。
现在我们来替换文件第1,2行的bin字符串,替换为sedtest:
# sed  '1,2s/bin/sedtest/' passwd            
root:x:0:0:root:/root:/sedtest/sh
proxy:x:13:13:proxy:/sedtest:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
我们可以使用sed的-n选项以及s命令的p选项来仅仅打印被替换的行:
# sed -n '1,2s/bin/sedtest/p' passwd
root:x:0:0:root:/root:/sedtest/sh
proxy:x:13:13:proxy:/sedtest:/bin/sh
使用s命令的g选项可以替换当前行所有符合模式的地方:
# sed -n '1,2s/bin/sedtest/pg' passwd
root:x:0:0:root:/root:/sedtest/sh
proxy:x:13:13:proxy:/sedtest:/sedtest/sh
该命令使用awk实现较复杂。
8.    r命令,从另一个文件中读文本
从new.txt文件读取内容附加到文件符合模式的指定行后面。
# sed '3r new.txt' passwd
root:x:0:0:root:/root:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
this line from new.txt
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
此操作使用awk较复杂。
9.    q命令,在符合模式行后面退出
# sed '/Operator/q' passwd
root:x:0:0:root:/root:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
# awk '{print;if (NR >= 3)exit}' passwd
root:x:0:0:root:/root:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
10.    l命令,显示文件控制字符
对之前使用new.txt文件稍作修改(加入一些控制字符)如下:
# cat new.txt
this line from new.txt
kkh

# 
使用l命令显示如下:
# sed  -n 'l' new.txt
this line from new.txt\033[B$
kkh$
\r$
#
Awk未发现有此功能。
11.    sed使用正则表达式进复杂替换
删除行首字母:
# sed 's/^[a-z]*//g'  passwd
在匹配文本后面增加文本:
# sed 's/[0-9][0-9]:/&8902:/g'  passwd
root:x:0:0:root:/root:/bin/sh
proxy:x:13:8902:13:8902:proxy:/bin:/bin/sh
operator:x:37:8902:37:8902:Operator:/var:/bin/sh
ftp:x:83:8902:83:8902:ftp:/home/ftp:/bin/sh
nobody:x:99:8902:99:8902:nobody:/home:/bin/sh
sshd:x:103:8902:99:8902:Operator:/var:/bin/sh
对password文件做如下操作:
a.    删除已:分隔的第一列
b.    将所有:替换为空格
c.    删除行尾sh
# sed 's/^[a-z]*://g' passwd  |  sed 's/:/ /g' | sed 's/sh$//g'
x 0 0 root /root /bin/
x 13 13 proxy /bin /bin/
x 37 37 Operator /var /bin/
x 83 83 ftp /home/ftp /bin/
x 99 99 nobody /home /bin/
x 103 99 Operator /var /bin/
删除行首两字符:
# echo "hello sed." | sed 's/^..//g'
llo sed.
删除行尾两字符:
# echo "hello sed." | sed 's/..$//g'
hello se
在sed字符串后面添加字符串” world”:
# echo "hello sed." | sed 's/sed/& world/g'
hello sed world.
    awk和sed的比较,我目前片面看来,sed更适合修改编辑文件,尤其是要修改行中某一字符串的时候很方便;而awk更适合用来取出每一行按指定分割符号分割出来的信息。
awk更复杂,感觉更像一种编程语言一样,而sed更像一个工具,用少量代码可以轻松搞定一些处理。这两工具各取所长,有的时候可以联合使用,处理起文本来就更好了。


shell文本过滤编程(九):sed命令

标签:脚本   正则表达式   sed   awk   

原文地址:http://blog.csdn.net/shallnet/article/details/38925653

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!