LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
123
返回列表 发新帖
楼主: yongjian

[精彩讨论]sed/awk的新问题[基本解决]

[复制链接]
 楼主| 发表于 2004-4-13 21:45:24 | 显示全部楼层
我这里用sed另外写了一个   没有嵌套,也许更好理解些:    源码:  cat file | sed -n '/^PROCESSED/{n;h;b};/^PARSING_FAILED/{H;x;p;n;x;b};/./!d;H'  最后由 wire 在 04-13-2004 09:46 编辑


强! 虽然文件头的空行存在,但仅一行代码,值得收藏!
 楼主| 发表于 2004-4-13 22:02:22 | 显示全部楼层
通过应用于真实数据源,wire兄的代码除了首行空行外,完全过滤出了我需要的数据,也解决了域分布不均的问题,不知wire兄是否能解释一下你的代码呢!感谢!
发表于 2004-4-14 09:58:05 | 显示全部楼层
最初由 yongjian 发表
通过应用于真实数据源,wire兄的代码除了首行空行外,完全过滤出了我需要的数据,也解决了域分布不均的问题,不知wire兄是否能解释一下你的代码呢!感谢!

那通过应用于真实数据源,在下的gawk脚本工作情况如何?给个反馈好吗?
看来楼主很喜欢"短命令",不过这恰恰是在下的弱项,呵呵~~~我比较注重扩展性。
发表于 2004-4-14 12:18:28 | 显示全部楼层
这段代码主要是利用sed里的hold space,它可以看作是一个缓冲区;原理其实很简单:sed在处理每行数据时,如遇到PROCESSED时清掉该缓冲,遇到PARSING_FAILED就将缓冲内容打印出来,其它的字符则追加到缓冲里。

首行空行的问题,将代码稍稍修改也可以解决:

  1. cat file | sed -n '/^PROCESSED/{n;h;b};/^PARSING_FAILED/{H;x;s/^\n//;p;n;h;p;b};/./!d;H'
复制代码
发表于 2004-4-14 16:02:38 | 显示全部楼层
不同的思路,对代码的复杂程度有很大的影响。
wire的思路
这段代码主要是利用sed里的hold space,它可以看作是一个缓冲区;原理其实很简单:sed在处理每行数据时,如遇到PROCESSED时清掉该缓冲,遇到PARSING_FAILED就将缓冲内容打印出来,其它的字符则追加到缓冲里。

我的思路是,逐行扫描,当遇到### EVENT ###行时,将其前一行及以后各行保存在pattern space中,直到遇到### END EVENT ###行,然后读取下一行,根据是否是PARSING_FAILED来进行相应的处理。由于最初楼主的描述不能确定能否出现下列情况:


  1. 1~906071~213435245(Apr 08 time 2004)
  2. ### EVENT ###
  3. aksldlamalsdf
  4. [color=blue]PARSING_FAILED[/color]
  5. asdjalskdfjal

  6. ### END EVENT ###
  7. PROCESSED

  8. [color=blue]something....[/color]

  9. 1~906072~458748239(Apr 08 time 2004)
  10. ### EVENT ###
  11. kdieiejr
  12. jkjviej

  13. ### END EVENT ###
  14. PARSING_FAILED

  15. 1~906073~8782293(Apr 08 time 2004)
  16. ### EVENT ###
  17. ierueio
  18. dkjfire

  19. ### END EVENT ###
  20. PARSING_FAILED

复制代码

不论如何,我是注重实践的,根据楼主最终的阐述wire的代码相对简单和实用。如工作中果真存在上述情况,再使用更准确的判断方法,当然也更麻烦。
个人观点,请楼主参考。
 楼主| 发表于 2004-4-15 00:00:22 | 显示全部楼层
嗯,r2007兄说的很对。我个人认为最重要的是准确!准确的数据输出是很重要的,因为经常的一些数据输出又是要feed到另外的程序中成为数据输入,如果不准确,产生的结果不可想象。在正确的获得数据的基础上,我才考虑代码的复杂程度。这也就是我偏向于取简单代码的原因,因为不管是r2007兄的,还是wire兄的,还是我们教主的,输出的数据都是符合要求的,是正确的。我都会一一保存并加以研究。我sed和awk都是刚学,不精,这样的代码,我还是要一段时间啃一啃的。

另外,根据最新的log数据和程序员的介绍(最后我还是找到了他), ### END EVENT ### 后的字串并不是只有PROCESSED和PARSING_FAILED, 其实还有QUEUED和WAITING,只是这两种情况出现很少,但是还是有的。不知各位的代码扩展性如何,如果有这两种情况,是否也能排除呢? 谢谢了!
 楼主| 发表于 2004-4-15 00:07:29 | 显示全部楼层
另复r2007上帖:
PARSING_FAILED字串是不会出现在EVENT body中的。所有对EVENT处理的四种结果(PROCESSED, PARSING_FIELED, QUEUED, WAITING)都只会在### END EVENT ###后出现,这是程序代码的结构。不过作为纯的扩展性研究,我认为情况可以设想的多些。只要最后能有一定的规律可寻就行。
发表于 2004-4-15 00:30:49 | 显示全部楼层
to yongjian:
我的脚本完全实现了你所说的功能。因为我的预想与你的实际情况是一致的。它具有很好的扩展性。
1. 你的时间戳以数字开头,以括号结尾。

  1.         if($0 ~ /^1.*\(.*\)$/)
  2.                 flag=1
复制代码

我的代码满足这点。

2. 内容行数不是问题,因为我的脚本不是根据这个来过滤的。

3. 至于域间空行,通通都会过滤掉,所以空行的行数无关系。

4. 这两种可能我的脚本都兼顾到,甚至还有扩展性,除了PROCESS or PARSING_FAILED,任意字符串都会被脚本识别。

5. 没错,域间分布不均匀性被脚本解决了。

6. 最后一个空行是无关重要的,如果存在,它总会被我的脚本过滤掉,请看这段巧妙的代码,我是在每个域上根据上下文加入空行的,而非在域下加空行(这有可能造成文件末尾带有空行)

  1.                         cnt++
  2.                         if(cnt>=2) print ""
复制代码

可见,从第二个域开始,在每个域上面加入空行。
发表于 2004-4-15 00:34:10 | 显示全部楼层
我那段烦琐的没有用到PROCESSED进行判断,应该不用修改,wire的需要修改一下。
发表于 2004-4-15 10:49:56 | 显示全部楼层
如果 ### END EVENT ### 后的字串还有QUEUED和WAITING或更多的话,则要如下修改:
将第一个正则式放入所有不需打印的特征串;第二个放入所有要打印的特征串;结构不用修改。

如:仅打印PARSING_FAILED的记录
  1. cat file | sed -n '/^\(PROCESSED\|QUEUED\|WAITING\)/{n;h;b};/^PARSING_FAILED/{H;x;p;n;x;b};/./!d;H'
复制代码

或者 打印PARSING_FAILED和WAITING的记录
  1. cat file | sed -n '/^\(PROCESSED\|QUEUED\)/{n;h;b};/^\(PARSING_FAILED\|WAITING\)/{H;x;p;n;x;b};/./!d;H'
复制代码

这里要求所有可能的特征串都要列进来。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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