LinuxSir.cn,穿越时空的Linuxsir!

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

多发发一些有意思的题做做呀![+sed/awk/regex练习]

[复制链接]
发表于 2006-3-6 03:59:28 | 显示全部楼层
Post by johnny_jiang
?是吗,yongjian兄是指最后会有空行,奇怪了,我把两个文件开始和末尾都加了很多空行,但是输出结果是好得,在不同得机器上果然不一样。郁闷ing...

hi Johnny, 我刚才拿你最后的code运行了一次,已经没有末尾的空行了。速度感觉也快了很多。
回复 支持 反对

使用道具 举报

发表于 2006-3-6 09:08:29 | 显示全部楼层
Post by yongjian
hi Johnny, 我刚才拿你最后的code运行了一次,已经没有末尾的空行了。速度感觉也快了很多。


那就好,期待yongjian兄的下一次考验,当然也希望各位兄弟们多出些题目来锻炼锻炼,小弟也会努力的
回复 支持 反对

使用道具 举报

发表于 2006-3-6 17:05:57 | 显示全部楼层
yongjian兄,能否把习题2的答案贴出来一下, 我看看,我只能做到下面这种结果:
Name                    SSN               Phone Number          Avg
------------------------------------------------------------------------------
John Doe            12345678    111-222-3456               $110.45
Dan Mercurio       11223456    222-202-4566               $26.34
Bruce Tobin         12334556    N/A                                $31.01
回复 支持 反对

使用道具 举报

发表于 2006-3-7 08:05:18 | 显示全部楼层
我没有答案啊... 我也是把自己做的贴出来大家讨论。这种题只有更好的方案,没有确定的答案。这是我做的,有点长了,而且不是真正100% awk,用到了一点shell,但基本上对两个文件的操作都是按awk来做的。
假定第一个文件叫file.1,第二个叫file.2。这是处理file.1的awk程序:

  1. BEGIN{FIELDWIDTHS="8 10 10 13 14 16 20 13 1"}
  2. NR>2 {
  3.         l=gensub(/ +/,"","g",$2)
  4.         f=gensub(/ +/,"","g",$3)
  5.         s=gensub(/ +/,"","g",$4)
  6.         if($5!~/\w/){
  7.             p="N/A"
  8.         }else{
  9.             p=gensub(/ +/,"","g",$5)
  10.         }
  11.         if($7!~/\w/){
  12.             e="N/A"
  13.         }else{
  14.             e=gensub(/^ +(\w+ \w+) +/,$1,"g",$7)
  15.         }
  16. printf "%-10s%-10s%-16s%-20s%-10s\n", f,l,s,p,e
  17. }
复制代码
这里用到了FIELDWIDTHS这个awk的内置变量。由于是数据库的表,每个单元都有长度定义,这样就好定位那些空单元。剩下是主程序,是shell写的。

  1. #!/bin/bash
  2. awk -f awk.file1 file.1 | while read line;do
  3.     f=$(echo $line|awk '{print $1}')
  4.     l=$(echo $line|awk '{print $2}')
  5.     echo | awk -v f="$f" -v l="$l" -v e="$line" '{
  6.                     while((getline<"file.2")>0) {
  7.                         if(index($0,/[0-9]+/)) {
  8.                             if($1~f && $2~l){
  9.                                 for(i=3;i<=NF;i++){
  10.                                     j=gensub(/^\$/,"","g",$i)
  11.                                     sum+=j
  12.                                 }
  13.                                 avg=sum/12
  14.                                 j=0;sum=0
  15.                                 printf "%-10s%-10s$%.2f\n",e," ",avg
  16.                                 break
  17.                             }
  18.                         }
  19.                     }
  20.                 }'
  21. done
复制代码

其实本来是一个大的awk程序,但由于定义了FIELDWIDTHS,如果写在一起第二个文件的处理就会出错。我现在也搞不定。所以没办法分开吧。我想肯定有高超的方法。
回复 支持 反对

使用道具 举报

发表于 2006-3-7 10:54:19 | 显示全部楼层
学习学习。。。
回复 支持 反对

使用道具 举报

发表于 2006-3-9 03:40:48 | 显示全部楼层
习题三:regex匹配练习。
要求:
1. 所有的匹配都要符合他们的逻辑意义。
2. 只需写出正则式的表达式。(不是要用sed/awk/perl等来做,是要写出正则式的表达式!)

IP类型
1. 一个真实的IP地址的表达式. 以xxx.xxx.xxx.xxx表达。
2. 一个A类地址的表达式。
3. 一个B类地址的表达式。
4. 一个C类地址的表达式。
5. 9.80.1.15 - 9.83.253.100 的所有IP表达式(netmask = 255.252.0.0)

时间类型:
1. 一年的第xxx天。(一年以小于366天为准)
2. 一个月的任何一天。(以mm/dd表示)
3. 2004年的任何一天。(以yyyy/mm/dd表示)
4. 一天的任何一个时间点。(以HH:MM表达)
5. 从16:10 - 第二天12:30的任何一个时间点。(以HH:MM表达)
6. 从2004年7月12日到2006年10月22日的任何一天。(以yyyy/mm/dd表达)

数字:
1. 有这样一个两位数,十位上的数总是比个位上的大。
2. 匹配从x03D9 - x8E9B 的所有16进制数。

电话:
0xx-xxx-xxx-xxxx的表达形式。
1. 第一个xx为任何一个两位数,不可以是00
2. 第二个xxx为任何一个3为数,不可以是,110,120,119,911,160.
3.第三个xxx为任何一个三位数,不可以是000.
4.第四个xxxx可以为任何4位数。

字符:

  1. "with "t" + '\<user@domain.com\>' and "b"."
复制代码

1.匹配除最外边的双引号之内的字串。字符"b"可有可无。
回复 支持 反对

使用道具 举报

发表于 2006-3-9 09:54:37 | 显示全部楼层
Post by yongjian
习题三:regex匹配练习。
要求:
1. 所有的匹配都要符合他们的逻辑意义。
2. 只需写出正则式的表达式。

IP类型
1. 一个真实的IP地址的表达式. 以xxx.xxx.xxx.xxx表达。
2. 一个A类地址的表达式。
3. 一个B类地址的表达式。
4. 一个C类地址的表达式。
5. 9.80.1.15 - 9.83.253.100 的所有IP表达式(netmask = 255.252.0.0)



想问个问题,真实的IP是指A,B,C类地址,不包括127.xxx.xxx.xxx的回路地址,对吗?
回复 支持 反对

使用道具 举报

发表于 2006-3-9 13:08:14 | 显示全部楼层
Post by johnny_jiang
想问个问题,真实的IP是指A,B,C类地址,不包括127.xxx.xxx.xxx的回路地址,对吗?

不是,127.xxx.xxx.xxx当然算一个真实的地址。但比如333.129.320.290就不是了。也就是说4个段的任何一个3位数都不能大于255.
回复 支持 反对

使用道具 举报

发表于 2006-3-9 13:58:05 | 显示全部楼层
先做一个简单的:
数字:
1. 有这样一个两位数,十位上的数总是比个位上的大。

awk 'BEGIN{FS=""} {if ($1>$2) print $0}'
回复 支持 反对

使用道具 举报

发表于 2006-3-9 14:23:41 | 显示全部楼层
Post by linux_now
先做一个简单的:
数字:
1. 有这样一个两位数,十位上的数总是比个位上的大。

awk 'BEGIN{FS=""} {if ($1>$2) print $0}'

我说过这个练习是做纯regex(正则表达式)的。不是用awk/sed来做的。请看清题目的要求。
回复 支持 反对

使用道具 举报

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

本版积分规则

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