免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3487 | 回复: 11
打印 上一主题 下一主题

[文本处理] 分组求和 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-06-07 14:15 |只看该作者 |倒序浏览
以下数据:
2015-12-31|a|张三|Y
2015-12-30|a|张三|Y
2015-12-29|a|张三|Y
2015-12-28|a|张三|Y
2015-12-28|a|张三|10
2015-12-31|b|李四|H
2015-12-30|b|李四|H
2015-12-29|b|李四|Y
2015-12-28|b|李四|H
2015-12-28|b|李四|3
2015-12-28|b|李四|H
2015-12-28|b|李四|H
2015-12-31|c|王五|0
2015-12-30|c|王五|H
2015-12-29|c|王五|H
2015-12-28|c|王五|2
2015-12-28|c|王五|Y

想经过如下处理:
按第三列相同的求出现Y和H的次数。如果第一样不是Y或者H就判断,显示$3|0(列入王五);如果下一行是Y或者N就+1,直到遇到不是Y或者N的行退出计算,显示$3|出现Y和H的次数和|出现H的次数和|出现Y的次数和(例如李四);如果每行都是Y,也显示$3|0(例如张三)

得到如下结果:
张三|0
李四|4|3|1
王五|0

请问如何实现?

论坛徽章:
60
20周年集字徽章-20	
日期:2020-10-28 14:04:3015-16赛季CBA联赛之北京
日期:2016-07-06 15:42:0715-16赛季CBA联赛之同曦
日期:2016-06-12 10:38:0915-16赛季CBA联赛之佛山
日期:2016-05-27 11:54:56黄金圣斗士
日期:2015-12-02 11:44:35白银圣斗士
日期:2015-11-25 14:32:43白银圣斗士
日期:2015-11-23 12:53:352015亚冠之布里斯班狮吼
日期:2015-10-21 16:55:482015亚冠之首尔
日期:2015-09-01 16:46:052015亚冠之德黑兰石油
日期:2015-08-31 11:39:192015亚冠之萨济拖拉机
日期:2015-08-28 21:06:5315-16赛季CBA联赛之广东
日期:2016-07-12 14:58:53
2 [报告]
发表于 2016-06-07 14:28 |只看该作者
看了N遍, 哥还是没抓住重点

论坛徽章:
0
3 [报告]
发表于 2016-06-07 14:45 |只看该作者
reyleon 发表于 2016-06-07 14:28
看了N遍, 哥还是没抓住重点

想经过如下处理:
按第三列相同的求出现Y和H的次数。如果第一样不是Y或者H就判断,显示$3|0(列入王五);如果下一行是Y或者N就+1,直到遇到不是Y或者N的行退出计算,显示$3|出现Y和H的次数和|出现H的次数和|出现Y的次数和(例如李四);如果每行都是Y,也显示$3|0(例如张三)

论坛徽章:
780
金牛座
日期:2014-02-26 17:49:58水瓶座
日期:2014-02-26 18:10:15白羊座
日期:2014-04-15 19:29:52寅虎
日期:2014-04-17 19:43:21酉鸡
日期:2014-04-19 21:24:10子鼠
日期:2014-04-22 13:55:24卯兔
日期:2014-04-22 14:20:58亥猪
日期:2014-04-22 16:13:09狮子座
日期:2014-05-05 22:31:17摩羯座
日期:2014-05-06 10:32:53处女座
日期:2014-05-12 09:23:11子鼠
日期:2014-05-21 18:21:27
4 [报告]
发表于 2016-06-07 15:36 |只看该作者
回复 1# alunfirst

为了测试方便,第三列我改成A B  C了

  1. awk -F'|' 'name!=$3{a[$3];name=$3;f=0;if($4=="Y"||$4=="H")f=1} f{if($4=="Y"||$4=="H")b[$3,$4]++;else f=0} END{for(i in a){if(b[i,"H"])print i"|"b[i,"Y"]+b[i,"H"]"|"b[i,"H"]"|"b[i,"Y"];else print i"|0"}}' i
  2. A|0
  3. B|4|3|1
  4. C|0
复制代码

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
5 [报告]
发表于 2016-06-07 15:45 |只看该作者
awk -F'|' 'BEGIN{_0000O0=FS;_000O00="+"+"+";_0O000O="-"-"-";_00O0O0=NR;_00O000="="=="=";_00O00O="=="=="==";_000O0O=NF;_00OO0O=_00O000+_0O000O+_00O00O-_000O00;_00OO00=_00O00O+_000O00+_00O000-_0O000O;_000OOO=_00OO0O*_00OO00-_000O00-_00O00O;_0O0000=-_00O000+_00OO00*_00OO0O-_000O00;_0O00OO=_0O000O;OFS=_0000O0;}{if(!_00000O[$_000OOO]++){_0000OO[++_0O00OO]=$_0O0000;if($(_00OO00*_00OO0O)!~/[YH]/)_0O0O0O[$_0O0000]=_00O000;}if($(_0O0000+_00O000)!~/[YH]/)_00OOO0[$_000OOO]=_00O00O;if(_00OOO0[$_0O0000])next;_0O00O0[$_000OOO,$(_0O0000+_00O000-_0O000O)]++;}END{for(_000OO0=_00O000+_000O00;_000OO0<=_0O00OO;_000OO0=_000OO0+_00O000+_0O000O){_0O0O00=_0000OO[_000OO0];_00O0OO=_0O00O0[_0O0O00,"Y"];_00OOOO=_0O00O0[_0O0O00,"H"];if(_0O0O0O[_0O0O00]||!_00O0OO||!_00OOOO)print _0O0O00,_000O00;else print _0O0O00,_00O0OO+_00OOOO,_00OOOO,_00O0OO}}' FILE
张三|0
李四|4|3|1
王五|0

评分

参与人数 1信誉积分 +10 收起 理由
sunzhiguolu + 10 超级给力!!!

查看全部评分

论坛徽章:
0
6 [报告]
发表于 2016-06-07 17:30 |只看该作者
Herowinter 发表于 2016-06-07 15:36
回复 1# alunfirst

为了测试方便,第三列我改成A B  C了


awk -F'|' 'name!=$3{a[$3];name=$3;f=0;if($4=="Y"||$4=="H")f=1} f{if($4=="Y"||$4=="H")b[$3,$4]++;else f=0} END{for(i in a){if(b[i,"H"])print i"|"b[i,"Y"]+b[i,"H"]"|"b[i,"H"]"|"b[i,"Y"];else print i"|0"}}' i
|0
王五|4|3|1
李四|4|2|2
张三|0

好像不行

论坛徽章:
0
7 [报告]
发表于 2016-06-07 17:32 |只看该作者
jason680 发表于 2016-06-07 15:45
awk -F'|' 'BEGIN{_0000O0=FS;_000O00="+"+"+";_0O000O="-"-"-";_00O0O0=NR;_00O000="="=="=";_00O00O="==" ...

好复杂
awk -F'|' 'BEGIN{_0000O0=FS;_000O00="+"+"+";_0O000O="-"-"-";_00O0O0=NR;_00O000="="=="=";_00O00O="=="=="==";_000O0O=NF;_00OO0O=_00O000+_0O000O+_00O00O-_000O00;_00OO00=_00O00O+_000O00+_00O000-_0O000O;_000OOO=_00OO0O*_00OO00-_000O00-_00O00O;_0O0000=-_00O000+_00OO00*_00OO0O-_000O00;_0O00OO=_0O000O;OFS=_0000O0;}{if(!_00000O[$_000OOO]++){_0000OO[++_0O00OO]=$_0O0000;if($(_00OO00*_00OO0O)!~/[YH]/)_0O0O0O[$_0O0000]=_00O000;}if($(_0O0000+_00O000)!~/[YH]/)_00OOO0[$_000OOO]=_00O00O;if(_00OOO0[$_0O0000])next;_0O00O0[$_000OOO,$(_0O0000+_00O000-_0O000O)]++;}END{for(_000OO0=_00O000+_000O00;_000OO0<=_0O00OO;_000OO0=_000OO0+_00O000+_0O000O){_0O0O00=_0000OO[_000OO0];_00O0OO=_0O00O0[_0O0O00,"Y"];_00OOOO=_0O00O0[_0O0O00,"H"];if(_0O0O0O[_0O0O00]||!_00O0OO||!_00OOOO)print _0O0O00,_000O00;else print _0O0O00,_00O0OO+_00OOOO,_00OOOO,_00O0OO}}' i
张三|0
李四|4|2|2
王五|4|3|1
|0

论坛徽章:
780
金牛座
日期:2014-02-26 17:49:58水瓶座
日期:2014-02-26 18:10:15白羊座
日期:2014-04-15 19:29:52寅虎
日期:2014-04-17 19:43:21酉鸡
日期:2014-04-19 21:24:10子鼠
日期:2014-04-22 13:55:24卯兔
日期:2014-04-22 14:20:58亥猪
日期:2014-04-22 16:13:09狮子座
日期:2014-05-05 22:31:17摩羯座
日期:2014-05-06 10:32:53处女座
日期:2014-05-12 09:23:11子鼠
日期:2014-05-21 18:21:27
8 [报告]
发表于 2016-06-07 17:33 |只看该作者
回复 7# alunfirst

我的结果和jason一样的,你确定你的真实数据和一楼一模一样?
   

论坛徽章:
0
9 [报告]
发表于 2016-06-07 17:42 |只看该作者
Herowinter 发表于 2016-06-07 17:33
回复 7# alunfirst

我的结果和jason一样的,你确定你的真实数据和一楼一模一样?


哦,可以。文件多了个空格

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
10 [报告]
发表于 2016-06-07 17:47 |只看该作者
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. my ($Name, $Print, $Continue) = ("", 0, 0);
  5. my %hStat = map {$_, 0} ("Y", "H");

  6. while (<>){
  7.     my ($name, $flag) = /([^|]+)[|](\w+)\Z/g;
  8.     if ($Name ne $name){
  9.         if ($Print){
  10.             my ($y, $h) = @hStat{"Y", "H"};
  11.             print join ("|", $Name, $y + $h, $h, $y), "\n";
  12.             ($Print, %hStat) = (0, ());
  13.         }
  14.         $Name = $name;
  15.         if ($flag eq 'H'){
  16.             $Print = $Continue = 1;
  17.             $hStat{$flag}++;
  18.             next;
  19.         }
  20.         $Print = $Continue = 0;
  21.         print join ("|", $Name, 0), "\n";
  22.         next;
  23.     }
  24.     if ($Continue){
  25.         if (!exists $hStat{$flag}){
  26.             $Continue = 0;
  27.             next;
  28.         }
  29.         $hStat{$flag}++;
  30.     }
  31. }
复制代码
perl abc.pl abc
--------------------------------------------
张三|0
李四|4|3|1
王五|0
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP