LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2068|回复: 12

请教怎么在grep的时候同时筛选两个条件?

[复制链接]
发表于 2010-10-24 17:21:24 | 显示全部楼层 |阅读模式
大家好,                                                                                 
我写了以下脚本,想把我想要的关键字在相应的代码文件里查找出来。                           
  1.                                                                                     
  2. #!/bin/bash                                                                              
  3. if [ -z "$3" ];                                                                           
  4. then                                                                                      
  5.     find "$1" \( -name \.svn -o -name \.git -o -name \.hg \) -prune -o \( -name \*\.c -o -
  6. name \*\.cc -o -name \*\.h -o -name \*\.sh -o -name \*\.py -o -name YBUILD -o -name [m,M]a
  7. kefile \) -exec grep -wnH  "$2" {} \;                                                     
  8. else                                                                                      
  9.     find "$1" \( -name \.svn -o -name \.git -o -name \.hg \) -prune -o \( -name \*\.c -o -
  10. name \*\.cc -o -name \*\.h -o -name \*\.sh -o -name \*\.py -o -name YBUILD -o -name [m,M]a
  11. kefile \) -exec  grep -wnHA$3 -B$3  "$2" {} \;                                            
  12. fi                                                                                       
复制代码
                                                                                 
但是,在这个脚本里,仍然不能把像以//开头的行给筛选掉,如果是在此次grep的結果的基础上      
再来一次grep以筛掉以//开头的行的话,最終的結果里,就丢失了文件名,以及相应的行数的信息了。
而这些信息对我阅读源代码而言,是最重要的。                                                
大家有什么好用的脚本吗?                                                                  
BTW,我现在在用vim+ctags.麻烦的是要在每一个代码文件夹下放一个类似.vimdc的文件,告诉vim到哪
去找tags文件。查找一个函数的定义,勉强还行,但是它无法找到所有调用该函数的地方。用cscope的
方案,我还在摸索。。
发表于 2010-10-24 18:14:58 | 显示全部楼层
用egrep或者grep -E就可以了。
grep -EwnH "$2|//"

用cscope的话,生成相关的文件,使用cs find d functionname就可以找出来了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-10-24 21:31:19 | 显示全部楼层
Post by linwhwylb;2117068
用egrep或者grep -E就可以了。
grep -EwnH "$2|//"

用cscope的话,生成相关的文件,使用cs find d functionname就可以找出来了

多谢指点,不过,好像你给的不太对吧,我是想把以//开头的行过滤掉,不在結果里显示出来。。我自己试了试,grep -EwnH  "$2&&!^//" 的方案,不过,还是不行。。。
回复 支持 反对

使用道具 举报

发表于 2010-10-25 11:09:18 | 显示全部楼层
grep -EwnH "$2&&!^//"???你在乱用正则表达式哇!:yun:
试试
  1. grep -nHE "^((|.)$2|(/[^/]|[^]/.).*$2).*"
复制代码
没测试过!:sorry
回复 支持 反对

使用道具 举报

发表于 2010-10-25 11:15:33 | 显示全部楼层
Post by huangying;2117109
多谢指点,不过,好像你给的不太对吧,我是想把以//开头的行过滤掉,不在結果里显示出来。。我自己试了试,grep -EwnH  "$2&&!^//" 的方案,不过,还是不行。。。


可以啊,怎么不行呢?
$ cat file1
//aaaaaaaaaaaaa
bbbbbbbbbbbb
cccceeefff
$ cat file1 | grep -E 'bb|//'
//aaaaaaaaaaaaa
bbbbbbbbbbbb
$ cat file1 | grep -vE 'bb|//'
cccceeefff
上面不是“//”不在结果显示出来吗?
回复 支持 反对

使用道具 举报

发表于 2010-10-25 12:13:43 | 显示全部楼层
Post by linwhwylb;2117173
可以啊,怎么不行呢?
$ cat file1
//aaaaaaaaaaaaa
bbbbbbbbbbbb
cccceeefff
$ cat file1 | grep -E 'bb|//'
//aaaaaaaaaaaaa
bbbbbbbbbbbb
$ cat file1 | grep -vE 'bb|//'
cccceeefff
上面不是“//”不在结果显示出来吗?
De Morgan法则:~(A∨B)=(~A∧~B)
grep -vE 'bb|//'的意思是:~(A∨B)=(~A∧~B)=(既要不显示“bb”所在行,又要不显示“//”所在行)
楼主要的应该是:C∧~D=(既然显示“$2”所在行,又不要显示“^//”所在行)
你当然可以简化为:~(~C∨D)=(不要显示这样的行:它不包含“$2”,或者包含“^//”)
这里关键的问题是:BRE和ERE里都没有对分组进行排除的构造,而$2和^//很显然又不是单个字符,不能用字符集的排除构造[^...]
回复 支持 反对

使用道具 举报

发表于 2010-10-26 23:52:12 | 显示全部楼层
如果可以接受sed的话,可以如下:
  1. sed -n "/\/\//d;/$2/p"
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-10-31 11:26:59 | 显示全部楼层
Post by Jockey;2117170
grep -EwnH "$2&&!^//"???你在乱用正则表达式哇!:yun:
试试
  1. grep -nHE "^((|.)$2|(/[^/]|[^]/.).*$2).*"
复制代码

没测试过!:sorry


真对不起,最近工作一直在忙,没空回复你的回帖,我测试了一下,你给的不行。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-10-31 11:30:21 | 显示全部楼层
Post by lastart;2117407
如果可以接受sed的话,可以如下:

  1. sed -n "/\/\//d;/$2/p"
复制代码

你的意思是在grep之后再来一次管道重定向吗?这样的话,可能grep結果的关键词高亮就没有了。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-10-31 11:31:21 | 显示全部楼层
Post by Jockey;2117181

你当然可以简化为:~(~C∨D)=(不要显示这样的行:它不包含“$2”,或者包含“^//”)

这个,好像很不错,能教我如何实现吗?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表