LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: yongjian

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

[复制链接]
发表于 2004-4-10 23:40:03 | 显示全部楼层
嗯,还是讲究一下强壮性好,呵呵~~~
其实,我的awk脚本还有一个关于强壮性(非PARSING_FAILED域的分布不均匀性)的小bug,大家去找一下这个bug。我这边快断电了,明天给答案,呵呵~~~
发表于 2004-4-11 14:37:33 | 显示全部楼层
Gawk的实现
开估了~~~
给出gawk脚本的最终版本。
除了满足楼主所有要求之外,还有以下特色:
它能适应"域间分布不均匀"(一个域以PARSING_FAILED或者其他字符串结尾)的可能性,并且巧妙地去掉头尾空行(详见运行结果)。

  1. [root@home root]# cat myawk6
  2. #!/bin/gawk
  3. {
  4.         if($0 ~ /^1.*\(.*\)$/)
  5.                 flag=1
  6.         if(flag==1 && $0 !~ /^$/){
  7.                 line[++i]=$0
  8.         }
  9.         if($0 == "### END EVENT ###"){
  10.                 endflag=1
  11.                 next
  12.         }
  13.         if(endflag==1){
  14.                 if($0 == "PARSING_FAILED"){
  15.                         cnt++
  16.                         if(cnt>=2) print ""
  17.                         for(j=1;j<=i;j++){
  18.                                 print line[j]
  19.                                 delete line[j]
  20.                         }
  21.                 }
  22.                 else{
  23.                         for(j=1;j<=i;j++){
  24.                                 delete line[j]
  25.                         }
  26.                 }
  27.                 i=0
  28.                 flag=0
  29.                 endflag=0
  30.         }
  31. }
复制代码

为了验证脚本的强壮性,不妨先给出楼主的变化文本:
---------------------------------------------------------------

1~906072~458748239(Apr 08 time 2004)
### EVENT ###
kdieiejr
jkjviej

### END EVENT ###
PARSING_FAILED

1~906071~213435245(Apr 08 time 2004)
### EVENT ###
aksldlamalsdf
asdjalskdfjal

### END EVENT ###
PROCESSED

1~906072~458748239(Apr 08 time 2004)
### EVENT ###
kdieiejr
jkjviej

### END EVENT ###
PARSING_FAILED

1~906073~8782293(Apr 08 time 2004)
### EVENT ###
ierueio
dkjfire

### END EVENT ###
PARSING_FAILED

1~906071~213435245(Apr 08 time 2004)
### EVENT ###
aksldlamalsdf
asdjalskdfjal

### END EVENT ###
PROCESSED

----------------------------------------------------------------
以上就是可能存在的"域间分布不均匀性"。
请看运行结果:
-------------------------------------------------------------------
[root@home root]# gawk -f myawk6 tmpdata
1~906072~458748239(Apr 08 time 2004)
### EVENT ###
kdieiejr
jkjviej
### END EVENT ###
PARSING_FAILED

1~906072~458748239(Apr 08 time 2004)
### EVENT ###
kdieiejr
jkjviej
### END EVENT ###
PARSING_FAILED

1~906073~8782293(Apr 08 time 2004)
### EVENT ###
ierueio
dkjfire
### END EVENT ###
PARSING_FAILED
-------------------------------------------------------------------

awk与C类似,具有很多高级语言的特性,这个脚本我利用了C常见的"标记"(flag)技术。:cool:
发表于 2004-4-11 20:54:22 | 显示全部楼层
教主兄给出的样本数据似乎有点片面,试试这个样本。虽然没有看到真正的源数据,按照楼主的描述,该文件能确定的关键字应该只有### EVENT ###,### END EVENT ###和PARSING_FAILED这3个,至于其它的都可能是任意字符。
  1. A~906072~458748239(Apr 08 time 2004)
  2. ### EVENT ###
  3. kdieiejr
  4. jkjviej

  5. ### END EVENT ###
  6. PARSING_FAILED

  7. 1~906071~213435245(Apr 08 time 2004)
  8. ### EVENT ###
  9. aksldlamalsdf
  10. asdjalskdfjal

  11. ### END EVENT ###
  12. PROCESSED
复制代码
发表于 2004-4-11 21:07:08 | 显示全部楼层
to r2007:
嗯,A~906072~458748239(Apr 08 time 2004)这类条目不可能是任意字符,它还是有一定格式的,比如说,(日期)这两个括号还是有的,因为这是日志文件嘛。我修正了一下上面的脚本,老兄请看一下。
发表于 2004-4-11 21:24:30 | 显示全部楼层
哦,我不是楼主,没有发言权。既然教主兄那么在意楼主的要求,比如说最后一个空行,不知是对“(日期)这两个括号还是有的”这个判定和楼主沟通过了,还是自己分析的。在楼主没有明确之前,或许正确或许错误,这好象不符合教主的风格吧?
发表于 2004-4-11 21:32:08 | 显示全部楼层
呵呵,只是就正常的日志逻辑,在下猜想而已。r2007兄教训的是。:p
 楼主| 发表于 2004-4-12 10:33:55 | 显示全部楼层
非常感谢home_king和r2007两位高手对此问题的深入研究!!!!!连我真的都没有想到这样的深度。原来是因为同事对其中PARSING_FAILED的内容要求的急,我也没有仔细的查看这个log文件的逻辑。看了两位对这个问题的分析后,我也认真的看了一下此log文件的特征(这个log有100000多行,为了不漏掉一些特殊的地方,看了整整2个小时,看到我流眼泪,现给出此文件的通项结构: (由于是程序生成的log文件,内容还算是很工整的。)
-----------------------------------------------------------
                              (文件最开头的空格)
1~Procoess ID ~UnixTimeFormat(Human Readable Time)
### EVENT ###
Contents (no blank new line. Could be multiple lines.)
             (BLANK NEW LINE as the separator)
### END EVENT ###
Receiptor Action (Only have two values: PROCESSED or PARSING_FAILED)
                      (BLANK NEW LINE as the separator)
-------------------------------------------------------------
根据以上的通项,可以给出两个通项的列子(非真实数据):
---------------------------------------------------

1~906098~4345678(Apr 09 20:03:59 2004)
### EVENT ###
eihvtkv
euiaek=1aee
eiiiovn="kwioeir3ad"
lcbjieio

### END EVENT ###
PROCESSED

1~906099~458748239(Apr 08 21:33:45 2004)
### EVENT ###
kdieiejr
jkjviej
eeku3="wefa1f3"
kl843fkl3="lsdjfirenvksndvir"
kwei3
klvjlkjq

### END EVENT ###
PARSING_FAILED

------------------------------------------------------------
这样的话,有几点就清楚了:
1。 时间戳的格式是固定的。一定是 “1~Process ID~UnixTimeFormat(Human Readable Time)
至于为什么是"1~"开头,我也不清楚。
2. EVENT的内容的长度,即Contents 的行数不是固定的。但是肯定没有空行。
3. "### END EVENT ###"前是肯定有空行的。
4. "### END EVENT ###"之后的字串只有两种可能: PROCESS or PARSING_FAILED.
5. 教主说的”域间分布不均匀性“是客观存在。(真对不起,最先的列子看不到这一点。)因为EVENT log中的PROCESSED和PARSING_FAILED是随机的,处理成了就是PROCESSED, 没有成功就是PARSING_FAILED. 所以它们出现的次序是无序的。
5.关于最后的一个空行的问题,因为我没有看到构造程序的源码,所以我不能确定,但是我认为最大可能是这个空行包括在了每一个EVENT生成的那段脚本中。,因为这是一个无限append的log文件,当时看到的只是那个时间点的EOF。
不知我是否解释了两位的一些疑点。shell版的学术研究氛围很浓,多得象两位这样的高人带动。在下受益匪浅!多谢多谢!
发表于 2004-4-12 10:47:24 | 显示全部楼层
最初由 yongjian 发表
-----------------------------------------------------------
                              (文件最开头的空格)
1~Procoess ID ~UnixTimeFormat(Human Readable Time)
### EVENT ###
Contents (no blank new line. Could be multiple lines.)
             (BLANK NEW LINE as the separator)
### END EVENT ###
Receiptor Action (Only have two values: PROCESSED or PARSING_FAILED)
                      (BLANK NEW LINE as the separator)
-------------------------------------------------------------

和我预想的分析一模一样,呵呵~~~
这样的话,有几点就清楚了:
1。 时间戳的格式是固定的。一定是 “1~Process ID~UnixTimeFormat(Human Readable Time)
至于为什么是"1~"开头,我也不清楚。
2. EVENT的内容的长度,即Contents 的行数不是固定的。但是肯定没有空行。
3. "### END EVENT ###"前是肯定有空行的。
4. "### END EVENT ###"之后的字串只有两种可能: PROCESS or PARSING_FAILED.
5. 教主说的”域间分布不均匀性“是客观存在。(真对不起,最先的列子看不到这一点。)因为EVENT log中的PROCESSED和PARSING_FAILED是随机的,处理成了就是PROCESSED, 没有成功就是PARSING_FAILED. 所以它们出现的次序是无序的。
5.关于最后的一个空行的问题,因为我没有看到构造程序的源码,所以我不能确定,但是我认为最大可能是这个空行包括在了每一个EVENT生成的那段脚本中。,因为这是一个无限append的log文件,当时看到的只是那个时间点的EOF。
不知我是否解释了两位的一些疑点。shell版的学术研究氛围很浓,多得象两位这样的高人带动。在下受益匪浅!多谢多谢!

我的Gawk最终脚本满足了你所有的要求。正如我说的,它具有灵活性和强壮性。容我道来。
1. 你的时间戳以数字开头,以括号结尾。

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

我的代码满足这点。
2. 内容行数不是问题,因为我的脚本不是根据这个来过滤的。
3. 至于域间空行,通通都会过滤掉,所以空行的行数无关系。
4. 这两种可能我的脚本都兼顾到,甚至还有扩展性,除了PROCESS or PARSING_FAILED,任意字符串都会被脚本识别。
5. 没错,域间分布不均匀性被脚本解决了。
6. 最后一个空行是无关重要的,如果存在,它总会被我的脚本过滤掉,请看这段巧妙的代码,我是在每个域上根据上下文加入空行的,而非在域下加空行(这有可能造成文件末尾带有空行)

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

可见,从第二个域开始,在每个域上面加入空行。

在下的工具观是,sed作为gawk的预处理或者末尾处理工具,而gawk是解决复杂问题的核心工具。

希望兄弟们也要参与这个shell氛围,贡献自己的一份力。在下课业繁重,有时侯兼顾不了。呵呵~~:p
发表于 2004-4-13 11:19:44 | 显示全部楼层
r2007 DX,看来看去不懂你的代码,能否具体介绍一下吗?
发表于 2004-4-13 17:22:33 | 显示全部楼层

我这里用sed另外写了一个

没有嵌套,也许更好理解些:

  1. cat file | sed -n '/^PROCESSED/{n;h;b};/^PARSING_FAILED/{H;x;p;n;x;b};/./!d;H'
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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