Chinaunix

标题: 寻找文件中的多行多列内容并输出对应行(比较繁琐,谢谢) [打印本页]

作者: greaterwei    时间: 2017-09-12 19:05
标题: 寻找文件中的多行多列内容并输出对应行(比较繁琐,谢谢)
本帖最后由 greaterwei 于 2017-09-14 18:10 编辑

文件refs.dat 包含以下多行多列内容
ACBACU        ACPRCU        …
ACCAFA        ADESXA        …
CATPAL        AOXSCH        …
CDACET        …        
CDCAZA        …        
…               
…               
        
文件cons.dat中内容如下:
ACBACU        1.397        0.854        2.782        0        0        0.211        4 4 4        4        4        4  ...
ACPRCU        3.535        2.441        1.565        0        0        0.373        3 2 3        3        2        3  ...
AOXSCH        2.159        1.340        3.080        0        0        0.365        3 2 3        3        2        3  ...
CATPAL         3.807        2.039        2.788        0        0        0.386        4 3 3        4        3        3  ...
CDCAZA        4.439        2.496        1.525        0        0        0.390        3 1 3        3        1        3  ...



refs.dat 中有约50列数据,每列长度不一;cons.dat中有约20万行数据,每行10列。

现在要求检测cons.dat 第一列中是否含有refs.dat中的内容并输出
检测规则为:先在cons.dat 第一列中 检测refs.dat 的第一列内容,然后提取对应行内容,并输出成文件1.dat;
                 再在cons.dat 第一列中 检测refs.dat的 第二列内容,然后提取对应行内容,并输出成文件2.dat;
                ...
                ...
                最后,未找到的refs.dat的内容按列生成新文件ref-left.dat                                          refs.dat中第n列的结果若全部找到,则在ref-left.dat中依然生成空列;若一个都没找到,依然生成空文件n.dat
               


如此,输出ref-left.dat的内容应为:
ACCAFA        ADESXA        …
CDACET        …                …
…                …        
…               

1.dat的内容应为:
ACBACU        1.397        0.854        2.782        0        0        0.211        4 4 4        4        4        4  ...
CATPAL         3.807        2.039        2.788        0        0        0.386        4 3 3        4        3        3  ...
CDCAZA        4.439        2.496        1.525        0        0        0.390        3 1 3        3        1        3  ...



2.dat的内容应为:
ACPRCU         3.535        2.441        1.565        0        0        0.373        3 2 3        3        2        3  ...
AOXSCH        2.159        1.340        3.080        0        0        0.365        3 2 3        3        2        3  ...



3.dat的内容应为:...

最后,如果能够把上述结果再分别直接输出至report.xls文件的各个sheet(即sheet1是ref-left.dat的内容,sheet2是1.dat的内容,sheet3是2.dat的内容,...)更好。

十分感谢!






作者: Newbee_Mofi    时间: 2017-09-12 22:10
太高深了,飘过~

作者: greaterwei    时间: 2017-09-12 22:43
回复 2# Newbee_Mofi

我可以一个一个的弄,但是那样的话太浪费时间了
作者: Newbee_Mofi    时间: 2017-09-12 22:55
回复 3# greaterwei

感觉你使用shell的水平 比我高多了 我才刚学会定时任务 简单的提数脚本编写
作者: greaterwei    时间: 2017-09-12 23:19
回复 4# Newbee_Mofi

我只会皮毛。。就是来求助的。。
作者: 龙牙地主天    时间: 2017-09-13 10:28
  1. awk 'NR==FNR{a[$1]=$0 ; next}{for(i in a) {if($1==i) {print a[$1] > "1.dat" ; $1="\t"} ;  if($2==i) {print a[$2] > "2.dat" ; $2="\t"}} $0=$0 ; print > "ref-left.dat"}' cons.dat refs.dat
复制代码

作者: zxy877298415    时间: 2017-09-13 10:44
回复 1# greaterwei


  1. awk 'FNR==NR{for(i=1;i<=NF;i++) a[NR" "i]=$i;m=NR;n=NF;next}{for(i=1;i<=m;i++) {for(j=1;j<=n;j++) if(a[i" "j]==$1) {print $0 >>j".dat";delete a[i" "j]}}}END{for(i=1;i<=m;i++) {for(j=1;j<=n;j++) {if(a[i" "j]) s=s?s" "a[i" "j]:a[i" "j]} b[++t]=s;s=""} for(i=1;i<=t;i++) if(b[i]) print b[i]>>"ref-left.dat"}' refs.dat  cons.dat
复制代码

excel的那个自己手工来吧,不知道shell怎么操作excel!
作者: 本友会机友会摄友会    时间: 2017-09-13 13:48
提示: 作者被禁止或删除 内容自动屏蔽
作者: wh7211    时间: 2017-09-13 21:13
回复 1# greaterwei

  1. awk 'FILENAME==ARGV[1]{a[$1]=$0;next}{for(i in a){for(j=1;j<=NF;j++){if($j~i){$j="";print a[i]>j".dat"}}}}{for(i=1;i<=NF;i++){s[i]=s[i]?s[i]" "$i:$i}}END{m1=split(s[1],t1);m2=split(s[2],t2);m=m1>m2?m1:m2;for(i=1;i<=m;i++){print t1[i],t2[i]>"ref-left.dat"}}' cons.dat refs.dat
复制代码

作者: greaterwei    时间: 2017-09-13 22:14
回复 6# 龙牙地主天

谢谢您的回复!您的代码可以运行,但是3列过后的数据没有输出
作者: greaterwei    时间: 2017-09-13 22:15
本帖最后由 greaterwei 于 2017-09-13 22:23 编辑

回复 9# wh7211

十分感谢您的回复!
您的代码可以运行,但是ref-left.dat 数据好像只能输出两列,三列之后的没有输出

作者: greaterwei    时间: 2017-09-13 22:22
回复 7# zxy877298415

谢谢前辈! 您的代码可以运行,但是只能输出第一列的数据
作者: greaterwei    时间: 2017-09-13 22:38
回复 8# 本友会机友会摄友会

谢谢前辈的回复。
1. 我的数据在20万行左右
2. 取交集,但是要输出的是对应处整行的内容:也就是在cons.dat 第一列中 遍历refs.dat第一列所有的内容, 找到对应后,输出cons.dat中此处整行的内容

作者: jason680    时间: 2017-09-14 07:26
回复 1# greaterwei

How about this way ...

$ awk 'function p(s){print "Output: "s}FNR==NR{for(n=1;n<=NF;++n)a[$n]=n;next}{if($1 in a){f=a[$1]".dat";print>f;if(a[$1]==c+1){p(f);++c}delete a[$1]}}END{for(n in a){f="ref-left.dat";print n>f;if(!d++)p(f)}}' refs.dat cons.dat
Output: 1.dat
Output: 2.dat
Output: ref-left.dat


作者: wh7211    时间: 2017-09-14 09:35
回复 11# greaterwei

refs.dat中一共有多少列?
作者: mwl940602    时间: 2017-09-14 09:46
awk 'NR==FNR{for(i=1;i<=NF;i++) {a[NR""i]=$i } col=(col<NF)?NF:col row=NR next } {b[$1]=$0 } END{for(i=1;i<=row;i++) {for(j=1;j<=col;j++) {if(b[a[i""j]]!="") {print b[a[i""j]] > j".dat"; a[i""j]=""} printf("%-6s ",a[i""j]) > ref-left".dat"} printf("\n") } }' resf.dat cons.dat
作者: mwl940602    时间: 2017-09-14 09:47
awk 'NR==FNR{for(i=1;i<=NF;i++) {a[NR""i]=$i } col=(col<NF)?NF:col row=NR next } {b[$1]=$0 } END{for(i=1;i<=row;i++) {for(j=1;j<=col;j++) {if(b[a[i""j]]!="") {print b[a[i""j]] > j".dat"; a[i""j]=""} printf("%-6s ",a[i""j]) > ref-left".dat"} printf("\n") } }' resf1.dat cons1.dat
作者: mwl940602    时间: 2017-09-14 09:47
awk 'NR==FNR{for(i=1;i<=NF;i++) {a[NR""i]=$i } col=(col<NF)?NF:col row=NR next } {b[$1]=$0 } END{for(i=1;i<=row;i++) {for(j=1;j<=col;j++) {if(b[a[i""j]]!="") {print b[a[i""j]] > j".dat"; a[i""j]=""} printf("%-6s ",a[i""j]) > ref-left".dat"} printf("\n") } }' resf.dat cons.dat
作者: mwl940602    时间: 2017-09-14 09:48
awk 'NR==FNR{for(i=1;i<=NF;i++) {a[NR""i]=$i } col=(col<NF)?NF:col row=NR next } {b[$1]=$0 } END{for(i=1;i<=row;i++) {for(j=1;j<=col;j++) {if(b[a[i""j]]!="") {print b[a[i""j]] > j".dat"; a[i""j]=""} printf("%-6s ",a[i""j]) > ref-left".dat"} printf("\n") } }' resf1.dat cons1.dat
作者: mwl940602    时间: 2017-09-14 09:48
awk 'NR==FNR{for(i=1;i<=NF;i++) {a[NR""i]=$i } col=(col<NF)?NF:col row=NR next } {b[$1]=$0 } END{for(i=1;i<=row;i++) {for(j=1;j<=col;j++) {if(b[a[i""j]]!="") {print b[a[i""j]] > j".dat"; a[i""j]=""} printf("%-6s ",a[i""j]) > ref-left".dat"} printf("\n") } }' resf.dat cons.dat
作者: 本友会机友会摄友会    时间: 2017-09-14 11:34
提示: 作者被禁止或删除 内容自动屏蔽
作者: jason680    时间: 2017-09-14 12:47
本友会机友会摄友会 发表于 2017-09-14 11:34
hi ,各位,我认为这是excel中点鼠标问题。
1 把两个txt导入excel。表1,表2。
2 交集即取重。生成表3。按 ...


...那是【偏执狂撸班】

Yes, You did it.


作者: 本友会机友会摄友会    时间: 2017-09-14 12:59
提示: 作者被禁止或删除 内容自动屏蔽
作者: mwl940602    时间: 2017-09-14 13:24
本友会机友会摄友会 发表于 2017-09-14 11:34
hi ,各位,我认为这是excel中点鼠标问题。
1 把两个txt导入excel。表1,表2。
2 交集即取重。生成表3。按 ...


鲁班好像还创造了锯子吧,人家也没有非用斧子解决问题。对好多初学者来说,遇到问题考虑的不是哪个工具好用,而是我会用哪个?您老用 PS无可厚非,喜欢也好,牛B也罢,去争论编程语言的好坏是没有意义的,实用才重要

作者: greaterwei    时间: 2017-09-14 17:57
回复 15# wh7211

两组数据。一组46列,另一组50列。谢谢前辈!
作者: greaterwei    时间: 2017-09-14 18:18
回复 14# jason680

谢谢前辈大神!但是您的代码运行的结果有点问题:首先输出的n.dat结果匹配的行数不对;其次 ref-left的结果只有一列。谢谢!

作者: greaterwei    时间: 2017-09-14 18:23
回复 21# 本友会机友会摄友会

首先非常感谢您!然后很遗憾,你给交集只能匹配输出单列,

然后我有用excel的MATCH和ADDRESS功能,是能完美解决问题;
但是20万行,50多列的数据,excel根本运行不了,总是卡死自动退出。。。


作者: greaterwei    时间: 2017-09-14 18:23
本帖最后由 greaterwei 于 2017-09-14 18:24 编辑

回复 21# 本友会机友会摄友会



作者: greaterwei    时间: 2017-09-14 18:28
回复 20# mwl940602

十分感谢,但是您的代码有 syntax error,您能再看下么? 谢谢

作者: 本友会机友会摄友会    时间: 2017-09-14 18:40
提示: 作者被禁止或删除 内容自动屏蔽
作者: 本友会机友会摄友会    时间: 2017-09-14 18:46
提示: 作者被禁止或删除 内容自动屏蔽
作者: wh7211    时间: 2017-09-14 21:16
回复 25# greaterwei

文件refs.dat内容如下:
ACBACU        ACPRCU        aaa
ACCAFA        ADESXA        bbb
CATPAL        AOXSCH        ccc
CDACET        111           ddd
CDCAZA

文件cons.dat内容如下:
ACBACU    1.397    0.854    2.782    0    0    0.211    4    4    4    4    4    4        
ACPRCU    3.535    2.441    1.565    0    0    0.373    3    2    3    3    2    3        
AOXSCH    2.159    1.340    3.080    0    0    0.365    3    2    3    3    2    3        
CATPAL    3.807    2.039    2.788    0    0    0.386    4    3    3    4    3    3        
CDCAZA    4.439    2.496    1.525    0    0    0.390    3    1    3    3    1    3

以下代码适合任意列,重新生成的文件ref-left.dat每列的行数是不同的,因此为了保证数据的准确性防止串列,增加了“---”符号。
  1. awk 'FILENAME==ARGV[1]{a[$1]=$0;next}{m=m>NF?m:NF;for(i in a){for(j=1;j<=NF;j++){if($j~i){$j="";print a[i]>j".dat"}}}}{for(i=1;i<=NF;i++){s[i]=s[i]?s[i]" "$i:$i}}END{for(i=1;i<=m;i++){split(s[i],t);n=n>length(t)?n:length(t)};for(i=1;i<=m;i++){split(s[i],t);for(j=1;j<=n;j++){t[j]=t[j]?t[j]:"---";p[j]=p[j]?p[j]" "t[j]:t[j]}}for(i=1;i<=n;i++){print p[i]>"ref-left.dat"}}' cons.dat refs.dat
复制代码


输出:
$ cat 1.dat
ACBACU    1.397    0.854    2.782    0    0    0.211    4    4    4    4    4    4        
CATPAL    3.807    2.039    2.788    0    0    0.386    4    3    3    4    3    3        
CDCAZA    4.439    2.496    1.525    0    0    0.390    3    1    3    3    1    3        

$ cat 2.dat
ACPRCU    3.535    2.441    1.565    0    0    0.373    3    2    3    3    2    3        
AOXSCH    2.159    1.340    3.080    0    0    0.365    3    2    3    3    2    3        

$cat ref-left.dat
ACCAFA ADESXA aaa
CDACET 111 bbb
--- --- ccc
--- --- ddd


作者: greaterwei    时间: 2017-09-14 21:55
本帖最后由 greaterwei 于 2017-09-14 22:04 编辑

回复 31# 本友会机友会摄友会

好的,十分感谢大神! 我再琢磨琢磨
作者: greaterwei    时间: 2017-09-14 22:02
回复 32# wh7211

十分感谢!您的代码在数据量少的时候非常好使!!!
但是数据一多后就不能输出文件了,而且ref-left就会出现错误,不知道什么原因。

数据输入的时候我需要注意什么么? 谢谢!


作者: mwl940602    时间: 2017-09-15 00:58
awk 'NR==FNR{for(i=1;i<=NF;i++){a[NR""i]=$i } col=(col<NF)?NF:col; row=NR; next}{b[$1]=$0 }END{for(i=1;i<=row;i++){for( j=1;j<=col;j++){if(b[a[i""j]]!=""){print b[a[i""j]] > j".dat"; a[i""j]="" } printf("%-6s ",a[i""j]) > "ref-left.dat"}printf("\n") > "ref-left.dat"} }' refs.dat cons.dat
作者: wh7211    时间: 2017-09-15 13:50
本帖最后由 wh7211 于 2017-09-15 14:53 编辑

回复 34# greaterwei

从给定的信息来看:
文件cons.dat:20万行
文件refs.dat:行数不确定,46列或50列


awk处理20万行数据不会有任何压力,请检查一下源文件是否是格式化文档。另外可以把文件ref-left出现错误的截图贴上来分析一下。




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