Chinaunix首页 | 论坛 | 博客
  • 博客访问: 240507
  • 博文数量: 69
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 15
  • 用 户 组: 普通用户
  • 注册时间: 2013-02-23 13:55
文章分类

全部博文(69)

文章存档

2016年(11)

2013年(58)

我的朋友

分类: LINUX

2016-05-09 12:05:42

原文地址:sed酷就一个字 作者:leonwang202

我是seder,不是awker

一、命令格式:
   sed [范围] [sy] [表达式] [命令]


如命令
   sed ‘1,5s/haha/hehe/g’ inputfile

将文件input的1至5行中的所有haha变为hehe,并输出到控制台

二、处理流程
sed命令处理流程大致是这样子:
   1.输入文件(或管道)一行一行地 进入“模式空间”
   2.在“模式空间”里,sed一行一行地处理数据
   3.数据完的数据一行一行地输出到文件或标准输出

有图有真相


三、示例

1.“或”条件查询
  grep "SEEK_MYSELF" -rn * | sed '/tags\|\(Binary\)/d'

 | ( ) 都属于正则表达式的POSIX扩展, 在sed里不直接支持 需要加转义字符\ 。
也就是说得这样使用: expr\|\(expr\)

同理,vim 中也这样使用“或”正则表达式来查询行



同理,grep中也这样
使用“或”
[root@local ~]# grep "dmr\|\(hwdata\)" install.log

grep搜文件,连续5个小写字母相连
[root@local ~]# grep "\([a-z]\)\1\1\1\1" aa.txt
[root@local ~]# grep '\([a-z]\)\1\{4\}' aa.txt




2.“且”条件查询

正则表达式只有“或”,没有“且”,所以只能“曲线救国”
vim 中这样使用“且”正则表达式来查询行


同理,sed中使用“且”
[
root@local ~]# sed -n '/leon.*hui\|\(hui.*leon\)/p' test


同理,grep中也这样使用“且”
[
root@local ~]# grep "leon.*hui\|\(hui.*leon\)" test


PS:
[root@local ~]# grep "leon.*hui\|\(hui.*leon\)" test
huileonkelly
lfksjdfskleonsdfsdhui
[root@local ~]# grep -e "leon.*hui\|hui.*leon" test
huileonkelly
lfksjdfskleonsdfsdhui
[root@local ~]# grep -E "leon.*hui|hui.*leon" test
huileonkelly
lfksjdfskleonsdfsdhui

这有一个麻烦,若patten有n个,那你再 就得写 n! 种情景。。。。
n 大于2 的时候,不得不用 grep | grep | grep         ???



3.cvs up时,只显示有更改的行


cvs up 2>&1 | sed '/^cvs/d


4.批量修改文件

网管部规范了CVS,要使用新的CVS账号密码
我一提交内核代码,傻眼了:代码是老账号co下来的,提交时用的还是老账号,提交失败
看了一下问题出在每个目录下面 CVS/Root 里有:
:ext:tester@192.168.1.130:/ljscm/cvsroot

把tester改为新账号leon即可

co下来的内核代码里,CVS/Root文件太多了,用如下命令批量修改
sed -i 's/tester/leon/g' `find . -name "Root"`


5.获取IP地址

[root]# cat test


[root]# sed -e 's/[^\/]*\/\/\([^\/]*\).*/\1/' test

6.贪婪法则 shell 正则表达式为 贪婪的(greedy)

[root]# cat test1
uid=500(guest) gid=500(others) groups=500(users),11(floppy)
 
下面把小括号内的值单独取出,如果利用贪婪规则,解决方案如下:
 
sed -e 's/[^(]*(\([^)]*\).*/\1/' test1
sed -e 's/[^(]*(\([^)]*\)[^(]*(\([^)]*\).*/\2/' test1
sed -e 's/[^(]*(\([^)]*\)[^(]*(\([^)]*\)[^(]*(\([^)]*\).*/\3/' test1
sed -e 's/.*(\(.*\))/\1/' test1
 
上面四条命令分别可以获得括号内的数值。如果是不利用贪婪规则,还有其他的解决方案:

//利用sed和awk
[root]# sed -e 's/[()]/:/g' test1 | awk -F: '{ print $2 }'    # guest
[root]# sed -e 's/[()]/:/g' test1 | awk -F: '{ print $4 }'    # others
[root]# sed -e 's/[()]/:/g' test1 | awk -F: '{ print $6 }'    # users
[root]# sed -e 's/[()]/:/g' test1 | awk -F: '{ print $8 }'    # floppy

//利用tr和cut
[root]# tr "()" ':' < test1 | cut -d: -f2     #guest
[root]# tr "()" ':' < test1 | cut -d: -f4     #others
[root]# tr "()" ':' < test1 | cut -d: -f6     #users
[root]# tr "()" ':' < test1 | cut -d: -f8     #floppy


目标是分别取出2008和2009两部分,利用贪婪规则如下:
[root]# cat test
aaa:2008

aaa:2009


[root]#sed -e 's/.*:\([^<]*\).*/\1/' test        # 得 2009
[root]#sed -e 's/[^:]*:\([^<]*\).*/\1/' test     # 得 2008
阅读(1869) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~