Chinaunix

标题: 笔试一道AWK文本处理题 [打印本页]

作者: stupid_lee    时间: 2014-09-02 11:47
标题: 笔试一道AWK文本处理题
123456      23           1000
234567      34           1234
345678      21           1234
456789      45           4532
234567      34           1233
234567      34           1234
345678      21           3445

其中第一列为ID号  第二列为级别   第三列为时间

题目要求,写一个AWK脚本处理文本,处理结果为

第一列显示ID
第二列过滤级别<30或者级别>40
第三列显示内容为,若为相同的ID号,计算时间之和



作者: yestreenstars    时间: 2014-09-02 11:50
这题似曾相识,是TX的?
作者: Herowinter    时间: 2014-09-02 12:02
回复 1# stupid_lee
  1. awk '$2<30||$2>40{a[$1" "$2]+=$3} END{for(i in a)print i,a[i]}' i
  2. 345678 21 4679
  3. 123456 23 1000
  4. 456789 45 4532
复制代码

作者: stupid_lee    时间: 2014-09-02 12:25
回复 2# yestreenstars

嘿嘿

   
作者: prcardin    时间: 2014-09-02 12:33
企鹅的
作者: Shell_HAT    时间: 2014-09-02 12:33
腾讯每年都考这个题目?
作者: stupid_lee    时间: 2014-09-02 12:34
回复 6# Shell_HAT
为什么你们都知道?我百度过结果没找到TX笔试题

   
作者: stupid_lee    时间: 2014-09-02 12:40
Herowinter 发表于 2014-09-02 12:02
回复 1# stupid_lee


膜拜
作者: wayflying    时间: 2014-09-02 12:46
腾讯面试给人的感觉是很学院气,喜欢问非常细节的问题,包括这类型笔试,如果不是天天写脚本,想一次性写好还是很难的。
作者: super皮波    时间: 2014-09-02 12:46
第一次回答这样的问题,有错误请指教
awk '{if($2>=30 && $2<=40) {a[$1]+=$3;b[$1]=$2;next}} END{for (i in a) print i " " b[i] " " a[i]}' mytest.txt

作者: super皮波    时间: 2014-09-02 12:50
貌似我写反了 你想留下的是<30和>40的
作者: 关阴月飞    时间: 2014-09-02 12:50
回复 10# super皮波


    请参考3楼
作者: stupid_lee    时间: 2014-09-02 12:52
回复 9# wayflying

我留空白了

   
作者: super皮波    时间: 2014-09-02 12:53
回复 12# 关阴月飞

恩 3楼写的确实简单,刚开始学shell,方法比较笨,思路不开阔,跟着各位前辈学习学习
   
作者: stupid_lee    时间: 2014-09-02 12:53
回复 10# super皮波

又多了一种参考,感谢

   
作者: super皮波    时间: 2014-09-02 12:54
回复 13# stupid_lee

下次面试见

   
作者: super皮波    时间: 2014-09-02 12:54
回复 15# stupid_lee

我这是笨方法,3楼是高大上的写法,你学习他的,忽略我的就可以了,我是重在参与
   
作者: stupid_lee    时间: 2014-09-02 12:56
回复 17# super皮波

能学到你的也不错了,三楼的确让人羡慕嫉妒


   
作者: Shell_HAT    时间: 2014-09-02 12:57
本帖最后由 Shell_HAT 于 2014-09-02 12:57 编辑

回复 11# super皮波


我这里测试的时候,有没有等号都不对。
  1. [root]# awk '{if($2>=30 && $2<=40) {a[$1]+=$3;b[$1]=$2;next}} END{for (i in a) print i " " b[i] " " a[i]}' a.txt
  2. 234567 34 3701

  3. [root]# awk '{if($2>30 && $2<40) {a[$1]+=$3;b[$1]=$2;next}} END{for (i in a) print i " " b[i] " " a[i]}' a.txt
  4. 234567 34 3701
复制代码

作者: super皮波    时间: 2014-09-02 13:02
回复 19# Shell_HAT

你指的是哪里的等号 我这里测试的时候没发现问题呢
样本如下
123456 23 1000
234567 34 1234
345678 21 1234
456789 45 4532
234567 34 1233
234567 34 1234
345678 21 3445
888888 35 1000
999999 30 1000

awk '{if($2>=30 && $2<=40) {a[$1]+=$3;b[$1]=$2;next}} END{for (i in a) print i" " b " " a}' mytest.txt
234567 34 3701
999999 30 1000
888888 35 1000


作者: Shell_HAT    时间: 2014-09-02 13:10
回复 20# super皮波


    你能否使用顶楼的数据,把3楼代码和你的代码的执行结果分别发出来看看。
作者: super皮波    时间: 2014-09-02 13:12
回复 21# Shell_HAT

我的正好写反了,我以为楼主想留下的是30到40之间的。楼主的本意是要过滤掉30到40之间的


   
作者: Shell_HAT    时间: 2014-09-02 13:15
回复 22# super皮波


知道了。
你的代码里面next命令是必须的吗?
作者: super皮波    时间: 2014-09-02 13:19
回复 23# Shell_HAT

next不是必须的,没啥作用,对awk用的不熟
   
作者: Shell_HAT    时间: 2014-09-02 13:23
本帖最后由 Shell_HAT 于 2014-09-02 13:23 编辑

回复 24# super皮波


还有就是 print 的时候直接用逗号就行了
  1. print i,b[i],a[i]
复制代码

作者: super皮波    时间: 2014-09-02 13:24
回复 25# Shell_HAT

多谢指教。


   
作者: wayflying    时间: 2014-09-02 13:44
仔细看了下3楼的,确实厉害,将域输出和数组下标非常巧妙地整合了。如果只用a[$1]+=$3也可以完成计算,但输出的结果缺少第二个域。

作者: stupid_lee    时间: 2014-09-02 13:52
回复 27# wayflying

TX考了好多awk的东西


   
作者: wayflying    时间: 2014-09-02 13:54
估计是面试游戏运维。
回复 28# stupid_lee


   
作者: super皮波    时间: 2014-09-02 13:57
回复 28# stupid_lee

你面试的是什么岗位?
   
作者: wayflying    时间: 2014-09-02 14:01
一般笔试awk,我觉得会求和和算平均值就够了(小数点保留2位置)。剩下的,工作实践中自己再去慢慢搞。
作者: reb00t    时间: 2014-09-02 14:32
  1. php练习来了。

  2. <?php
  3. $fa = file('200.txt');
  4. $newarr=array();
  5. foreach ($fa as $k => $v) {
  6.    $arr=explode(" ",  preg_replace("/[ ]+/"," ", $v));   
  7.     if ($arr[1]>40 || $arr[1]<30) {   
  8.        $newarr[$arr[0]." ".$arr[1]]+=$arr[2];
  9.     }
  10. }
  11. foreach ($newarr as $kk=> $vv) {
  12.    echo $kk." ".$vv."\n";
  13. }

  14. ?>

  15. 结果:
  16. 123456 23 1000
  17. 345678 21 4679
  18. 456789 45 4532
复制代码

作者: love_shift    时间: 2014-09-02 15:39
目测一下,做个练习
  1. root@ubuntu:~/cu_test# more t.py
  2. #!/usr/bin/env python
  3. #
  4. #v2.7

  5. def getData(fname):
  6.         with open(fname,'r') as f:
  7.                  s = f.read().strip().split('\n')
  8.         return s
  9. def dataJudge():
  10.         container = {}
  11.         fd_list = getData('file')
  12.         for item in fd_list:
  13.                 k = [ int(x) for x in item.split()]
  14.                 if k[1] < 30 or k[1] > 40:
  15.                    if k[0] in container.keys():
  16.                       container[k[0]][2] += k[2]
  17.                    else:
  18.                              container[k[0]] = k
  19.         for i,v in container.items():
  20.             print  ' '.join([ str(x) for x in v ])


  21. if __name__ ==  '__main__':
  22.         dataJudge()

  23. root@ubuntu:~/cu_test# ./t.py
  24. 123456 23 1000
  25. 456789 45 4532
  26. 345678 21 4679
  27. root@ubuntu:~/cu_test# more file
  28. 123456      23           1000
  29. 234567      34           1234
  30. 345678      21           1234
  31. 456789      45           4532
  32. 234567      34           1233
  33. 234567      34           1234
  34. 345678      21           3445
复制代码

作者: cao627    时间: 2014-09-02 15:47
回复 1# stupid_lee

123456      23           1000
123456      24           1000


你的数据中会不会有如上情况出现,即123456这个ID在23级中花费了1000s,在24级中也花了1000s,那么这个ID共花了2000s不是吗。

作者: reb00t    时间: 2014-09-02 15:53
回复 33# love_shift


    哈哈 ,顶楼上,以后我写php,你写python吧~~ 气氛搞起。
作者: stupid_lee    时间: 2014-09-02 16:15
回复 34# cao627

这个 级别是实时的,所以和ID一一对应

   
作者: stupid_lee    时间: 2014-09-02 22:16
回复 33# love_shift
我只能45度角,仰望天空了





   
作者: henianen22    时间: 2014-09-03 12:34
上个星期去了,有这题,awk '$2<30 || $2>40{a[$1]+=$3;b[$1]=$2}END{for(i in a)print i,b[i],a[i]}' k.txt
作者: Kasiotao    时间: 2014-09-03 14:55
  1. awk '{if($2<30 || $2>40)next;a[$1" "$2]+=$3}END{for(i in a){print i,a[i]}}' testfile
复制代码

作者: Nathon99    时间: 2014-09-04 17:27
回复 3# Herowinter


    {a[$1" "$2]+=$3}
这个是什么意思呢?
作者: Herowinter    时间: 2014-09-04 19:35
回复 40# Nathon99

a[$1" "$2]=a[$1" "$2]+$3

在前面累积的计数上加上当前第3列的值。
作者: wuxiaobo_2009    时间: 2014-09-11 13:07
回复 3# Herowinter
明显误读了 第三个条件

   
作者: Herowinter    时间: 2014-09-11 13:16
回复 42# wuxiaobo_2009

楼主的需求和示例文本里没说对于这种情况怎么处理:

345678      21           1234
345678      22           3456

即$1一样,$2不一样时怎么处理。对我来说这个算是一个
未定义行为,我只是按自己的理解实现了下,只处理前2列
都一样的文本,有出入莫怪。
作者: wuxiaobo_2009    时间: 2014-09-11 13:34
回复 19# Shell_HAT


    3701 为什么说明不对呢?
作者: baoersc    时间: 2014-09-11 15:07
回复 3# Herowinter
高手,我捣鼓半天都没有下文呢。对字符下标数组理解不够。

   
作者: ziyunfei    时间: 2014-09-12 13:02
这面试题也太简单了
作者: 酋长海布里    时间: 2014-09-12 14:12
回复 41# Herowinter


    数组下标是$1" "$2怎么理解?
作者: stupid_lee    时间: 2014-09-12 15:32
回复 43# Herowinter

不好意思是我没讲清楚,不过原题和你理解的是一样的,第二列的级别是实时的,因此第一列相同,第二列则也就相同了。
哪些误解题目的人们,就当是多练习了一下下吧,我相信不管怎么变Herowinter一分钟内肯定都能搞定的


   
作者: 李满满    时间: 2014-09-12 15:57
学生党:飘过~
[yhsafe@b10-1b ~]$ awk '$2<30||$2>40{b[$1]=$2;a[$1]=(a[$1]=="")?$3:a[$1]+$3}END{for(x in a){print x,b[x],a[x]}}' yhsafe.txt        
  
123456 23 1000
456789 45 4532
345678 21 4679

作者: 聆雨淋夜    时间: 2014-11-10 20:48
awk '{if($2>30&&$2<40)next}{a[$1"\t"$2]=a[$1"\t"$2]+$3}END{for(i in a)print i,a[i]}' file
作者: wiliiwin    时间: 2014-11-11 17:50
本帖最后由 wiliiwin 于 2014-11-11 18:16 编辑

python来一发
  1. #!/usr/bin/python
  2. def getConfig():
  3.     f = open("29.txt","r")
  4.     dic = {}
  5.     key = ()
  6.     for line in f:
  7.         line = line.strip()
  8.         line = line.split()
  9.         if int(line[1])<30 or int(line[1])>40:
  10.            key = (line[0],line[1])
  11.            if key in dic:
  12.                dic[key]= dic[key]+int(line[2])
  13.            else:
  14.                dic[key] = int(line[2])
  15.     for keys in dic.keys():
  16.           print keys[0],keys[1],dic[keys]

  17. if __name__ == '__main__':
  18.     getConfig()
复制代码
  1. # 3.py
  2. 456789 45 4532
  3. 123456 23 1000
  4. 345678 21 4679
复制代码

作者: love_shift    时间: 2014-11-12 22:56
这道题为什么这么火, 练习下。
  1. #!/usr/bin/env python
  2. #
  3. #python 2.7
  4. from fileinput import input
  5. d = {}
  6. for l in input('tmp'):
  7.         n = [ int(x) for x in l.split() ]
  8.         if n[1] < 30 or n[1] > 40:
  9.                 if n[0] in d.keys():
  10.                         d[n[0]][1] += n[2]
  11.                 else:
  12.                         d[n[0]] = n[1:]
  13. for k,v in d.items():
  14.         print '{}\t{}\t{}'.format(k,v[0],v[1])
复制代码
  1. root@ubuntu:/tmp# python t.py
  2. 123456        23        1000
  3. 456789        45        4532
  4. 345678        21        4679
复制代码

作者: linuxboy823    时间: 2014-11-14 09:43
$ awk '{if($2<30||$2>40) a[$2]++;}END{for (i in a) print $1,i,a[i]}' urfile3
345678 21 2
345678 23 1
345678 45 1

作者: linuxboy823    时间: 2014-11-14 09:45
awk '{if($2<30||$2>40) a[$2]+=$3;}END{for (i in a) print $1,i,a[i]}' urfile3
345678 21 4679
345678 23 1000
345678 45 4532

作者: linuxboy823    时间: 2014-11-14 09:45
awk '{if($2<30||$2>40) a[$2]+=$3;}END{for (i in a) print $1,i,a[i]}' urfile3
345678 21 4679
345678 23 1000
345678 45 4532

作者: linuxboy823    时间: 2014-11-14 09:47
$ awk '{if($2<30||$2>40) a[$1]+=$3;}END{for (i in a) print $1,i,a[i]}' urfile3
345678 123456 1000
345678 345678 4679
345678 456789 4532





欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2