[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

gawk如何实现具有相同字段的多行则输出最后字段数值最大的行

本帖最后由 pcl_test 于 2016-7-18 19:41 编辑

有文本a.txt,内容如下
  1. AAA,BBB,CC,D,EEEEEEEE,950
  2. SSS,GGG,CC,F,EEEEEEEE,1000
  3. SSS,GGG,CC,F,EEEEEEEE,800
  4. PPP,YYY,FF,E,DDDDDDDD,1250
  5. KKK,JJJ,HH,D,TTTTTTTT,400
  6. KKK,JJJ,HH,D,TTTTTTTT,1200
  7. KKK,JJJ,HH,D,TTTTTTTT,800
复制代码
文件中存在以下情况,2条以上的记录前5项相同,最后1项不同,如:
SSS,GGG,CC,F,EEEEEEEE,1000
SSS,GGG,CC,F,EEEEEEEE,800

KKK,JJJ,HH,D,TTTTTTTT,400
KKK,JJJ,HH,D,TTTTTTTT,1200
KKK,JJJ,HH,D,TTTTTTTT,800
希望输出结果:
AAA,BBB,CC,D,EEEEEEEE,950
SSS,GGG,CC,F,EEEEEEEE,1000
PPP,YYY,FF,E,DDDDDDDD,1250
KKK,JJJ,HH,D,TTTTTTTT,1200

即:
1、前5项没有相同记录的,直接输出;
2、前5项有相同记录的,输出第6项数字最大的记录。

希望高手指点,谢谢!

本帖最后由 pcl_test 于 2016-7-18 20:05 编辑
  1. //&cls&cscript -nologo -e:jscript "%~f0"<"1.txt"&pause&exit
  2. var map={}, s='';
  3. while(!WSH.StdIn.AtEndOfStream){
  4.     var str = WSH.StdIn.ReadLine();
  5.     var a = str.replace(/[^\,]+$/, '').replace(/^\s*/, '');
  6.     var b = str.replace(/^.+\,/g, '').replace(/\s*$/, '');
  7.     if(!map[a]){
  8.         map[a]=b;
  9.      }else{
  10.         if(map[a]>=b)map[a]=b;
  11.      }
  12. }
  13. for(var m in map)s+=m+map[m]+'\r\n'
  14. WSH.Echo(s);
复制代码
1

评分人数

TOP

谢谢pcl_test ,我最想知道的gawk怎样解决这个问题

TOP

本帖最后由 bailong360 于 2015-2-28 15:34 编辑
  1. @echo off
  2. <%0 more +4 >$.awk
  3. gawk -f $.awk a.txt
  4. del $.awk&exit
  5. BEGIN {FS=","}
  6. {
  7.     if (data[$1","$2","$3","$4","$5]==0)
  8.         data[$1","$2","$3","$4","$5]=$6
  9.      else
  10.         data[$1","$2","$3","$4","$5]=$6>data[$1","$2","$3","$4","$5]?$6:data[$1","$2","$3","$4","$5]
  11.    
  12. }
  13. END {
  14.     for (line in data)
  15.         printf("%s,%d\n",line,data[line])>"$new.txt"
  16. }
复制代码
拙作,楼下既然有更好的代码了,就放在这里当作纪念吧

TOP

本帖最后由 CrLf 于 2015-2-27 19:21 编辑

回复 4# bailong360


    直接用 data[$1,$2,$3,$4,$5] 就好,这里的 , 相当于一个文件分割符

TOP

本帖最后由 bailong360 于 2015-2-27 19:27 编辑

回复 5# CrLf


    我原先也是这样的,后来发现输出以后没有逗号,所以改成了这个样子

看了下兄弟楼下的代码,感叹自己的思路实在是僵硬啊..

TOP

本帖最后由 CrLf 于 2015-2-27 22:31 编辑

gawk -F"," "$6>data[$1,$2,$3,$4,$5]{data[$1,$2,$3,$4,$5]=$0} END{for (line in data)print data[line]>\"$new.txt\"}" a.txt
代码有误,更正见 10 楼
1

评分人数

TOP

本帖最后由 yiwuyun 于 2015-2-28 08:02 编辑

佩服。好像这样也可
  1. gawk -F"," "$6>data[$1$2]{data[$1$2]=$0} END{for (line in data)print data[line]}" a.txt
复制代码
改成这样:
  1. gawk -F"," "$6>a[split(data[$1$2],a,\",\")]{data[$1$2]=$0} END{for (line in data)print data[line]}" 2.txt
复制代码
1

评分人数

    • CrLf: a[split(data[$1$2],a,\&quot;,\&quot;)] .技术 + 1

TOP

感谢大家的帮助,今天没法评分了,明天补上

TOP

本帖最后由 CrLf 于 2015-2-27 22:30 编辑

卧槽,大伙没发现我写错了吗,用 $6 和 $0 来比较的...
修改下,还是像 4 楼那样用逗号分隔吧
  1. gawk -F"," -v d="," "$6>data[$1 d $2 d $3 d $4 d $5]{data[$1 d $2 d $3 d $4 d $5]=$6} END{for (line in data)print line d data[line]}" a.txt
复制代码
或用 gsub
  1. gawk -F"," "$6>data[$1,$2,$3,$4,$5]{data[$1,$2,$3,$4,$5]=$6} END{for (line in data){l=line;gsub(/\x1c/,\",\",l);print l \",\" data[line]}}" a.txt
复制代码
分隔符不同,排序居然还不一样
1

评分人数

TOP

本帖最后由 yiwuyun 于 2015-2-28 08:26 编辑

$6和$0比较,就是$6和$6比较。逗号分隔符的计算就是以最后一个为准。认识错了。
gawk -F"," "$6>int(data[$1$2]){data[$1$2]=$0} END{for(line in data)print data[line]}" a.txt

TOP

回复 10# CrLf


感谢帮助,我对这个还是了解的太少了

TOP

回复 8# yiwuyun

谢谢帮助,我觉得还是data[$1$2$3$4$5]比较好,否则第三到5列要是有不一样的就无法区分了

TOP

本帖最后由 CrLf 于 2015-2-28 13:36 编辑

回复 8# yiwuyun


    a[split(data[$1$2],a,\",\")] 好精巧!可以去掉 \",\",因为你已经设了 FS 了
    但 $1$2 是没有分隔符的,怎么区分 SSS,GGG 和 SSSG,GG 呢?
1

评分人数

TOP

嗯。多谢指正,考虑不周,实际应用应多取几段,或者再多加几根下划线。这样重复的概率就小多了。

TOP

返回列表