免费注册 查看新帖 |

Chinaunix

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

又遇难题,恳请帮助 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-09-20 11:41 |只看该作者 |倒序浏览
本帖最后由 bioinfor 于 2010-09-23 11:05 编辑

文件中数据分两列,两列间以table键格开,两列的数据行数可能不相同,其中第一列存在存放一个或两个数据的单元格,一个数据的为单个名称如LDHA,两个数据的用/符号分开,其中/表示或的意思,如MFSD3 / LOC113655表示MFSD3或LOC113655,但MFSD3 / LOC113655仍占第一列的一个单元格,第二列不存在/分开的名称,因此第二列单元格均只有一个数据。如下:

LDHA  ZNFX1
GABPB2  MFSD3
HDHD2  PNPO
STYXL1 / DUSP24  PLEKHA3
PNPO  PDCD1LG2
SECISBP2  CYBRD1
SLC12A9  DUSP24
MCOLN1  MYT1L
MFSD3 / LOC113655  FYCO1

将相同名称的输出来,中间以table键相隔开,如上面应该输出:
PNPO  PNPO
STYXL1 / DUSP24 DUSP24
MFSD3 / LOC113655 MFSD3


实际文件可能比较大,大约有4000行左右。

附上实际数据。


谢谢!

Book3.rar

10.26 KB, 下载次数: 82

论坛徽章:
0
2 [报告]
发表于 2010-09-20 11:53 |只看该作者
2个方法
第一个直接复制到excl表格中,然后选择排序,5秒内搞定
第二个办法,用perl正则取第一列作为hash的key,整列做值,最后按key  foreach输出,耗时2分钟

论坛徽章:
0
3 [报告]
发表于 2010-09-20 14:44 |只看该作者
可以考虑用列表就够了,不过数据的确很庞大,做个循环读好了,也不要用列表了

论坛徽章:
0
4 [报告]
发表于 2010-09-20 15:14 |只看该作者
用hash应该还是挺快的。

论坛徽章:
0
5 [报告]
发表于 2010-09-20 21:02 |只看该作者
如图,你的数据从第991行开始就只有1列了
请准确的描述一下需求

论坛徽章:
0
6 [报告]
发表于 2010-09-21 21:14 |只看该作者
本帖最后由 shangat 于 2010-09-24 10:32 编辑

回复 1# bioinfor
  1. use strict;
  2. use warnings;

  3. my ( @arr, $key, $values, $temp );
  4. my %hash;

  5. open A,"Book.txt" or die;
  6. while ( <A> ) {
  7.         chomp;
  8.         @arr = split;
  9.         if ( @arr % 2 ) {
  10.                 $hash{$_} =  "###";
  11.         }
  12.         else {
  13.                 $values = $arr[-1];
  14.                 s/(\w.*)\s+$values/$1/;
  15.                 $hash{$_} = $values;
  16.         }
  17. }

  18. foreach $key ( keys %hash ) {
  19.         @arr = split /\s+/,$key;
  20.         if ( @arr == 3 ) {
  21.                 foreach $temp ( @arr[0,2] ) {
  22.                         if ( ( $values ) = grep $temp eq $_, values %hash ) {
  23.                                 printf ("%-25s\t%-15s\n",$key, $values);
  24.                         }
  25.                 }
  26.         }
  27.         else {
  28.                 if ( ( $values ) = grep $arr[0] eq $_, values %hash ) {
  29.                         printf ("%-25s\t%-15s\n", $key, $values);
  30.                 }
  31.         }
  32. }
复制代码
Q1:
5楼 发表于 2010-09-20 21:02  | 只看该作者

如图,你的数据从第991行开始就只有1列了

Q2:还要先对 Book3.txt 处理一下,含有 ^M
  1. sed -n 's/\r//p' Book.txt >book.txt
复制代码
或者
  1. dos2unix Book.txt
复制代码

论坛徽章:
0
7 [报告]
发表于 2010-09-22 11:12 |只看该作者
\w.*  
这是要匹配啥?

论坛徽章:
0
8 [报告]
发表于 2010-09-23 10:48 |只看该作者
本帖最后由 bioinfor 于 2010-09-23 10:56 编辑
2个方法
第一个直接复制到excl表格中,然后选择排序,5秒内搞定
第二个办法,用perl正则取第一列作为hash ...
xti9er 发表于 2010-09-20 11:53


EXCEL不行,因为第一列的数据和第二列的数据行数不一样,往往第一列的要多一些,所以用眼来比对不太现实。




谢谢shangat 的代码,但为什么我运行如下例子时
LDHA  ZNFX1
GABPB2  MFSD3
HDHD2  PNPO
STYXL1 / DUSP24  PLEKHA3
PNPO  PDCD1LG2
SECISBP2  CYBRD1
SLC12A9  DUSP24
MCOLN1  MYT1L
MFSD3 / LOC113655  FYCO1


没有得到应有的结果:

PNPO  PNPO
STYXL1 / DUSP24 DUSP24
MFSD3 / LOC113655 MFSD3


另外,我使用我上传的Book3.rar文件中的数据运行了一下,结果不太对,第一列中存在而第二列没有的也输出来了
如:
STX18                                   STX18                
QRSL1                                   QRSL1


STX18在第一列存在,第二列没有这个数据。

另外:Q2:还要先对 Book3.txt 处理一下,含有 ^M
^M是什么?

论坛徽章:
0
9 [报告]
发表于 2010-09-24 10:46 |只看该作者
回复 8# bioinfor

A1:原来的代码为我对991 行之后添加内容进行操作,没有考虑到存在单列数据,并且 while 循环中的匹配也不对,不好意思
  1. CSTF2T        GALNT4
  2. CTDSPL2 / HSPC129        RANBP6
  3. CTSA / PPGB        EYA1
  4. CTSL1 / CTSL           991
  5. CYB5B / CYB5-M           992
  6. CYB5R4 / NCB5OR           993
  7. CYP1B1           994
  8. CYP51A1           995
复制代码
另外,我使用我上传的Book3.rar文件中的数据运行了一下,结果不太对,第一列中存在而第二列没有的也输出来了

在于匹配时哈希的键和值一样了,当然会匹配上,自己太不细心了
A2:
另外:Q2:还要先对 Book3.txt 处理一下,含有 ^M

自己找答案

代码已修改

论坛徽章:
16
IT运维版块每日发帖之星
日期:2015-08-24 06:20:00综合交流区版块每日发帖之星
日期:2015-10-14 06:20:00IT运维版块每日发帖之星
日期:2015-10-25 06:20:00IT运维版块每日发帖之星
日期:2015-11-06 06:20:00IT运维版块每日发帖之星
日期:2015-12-10 06:20:00平安夜徽章
日期:2015-12-26 00:06:302016猴年福章徽章
日期:2016-02-18 15:30:34IT运维版块每日发帖之星
日期:2016-04-15 06:20:00IT运维版块每日发帖之星
日期:2016-05-21 06:20:00综合交流区版块每日发帖之星
日期:2016-08-16 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-14 06:20:00
10 [报告]
发表于 2010-10-03 13:12 |只看该作者
回复 1# bioinfor

一点都不难,但是比较烦,囧。
调试了很久,╮(╯▽╰)╭,按照你的数据规则,以下这个脚本应该没问题。有问题站短我


  1. #!/bin/awk -f
  2. # author :expert1
  3. #date :2010-10-03

  4. #name :test.awk

  5. #USAGE: awk -f test.awk book3 book3

  6. NR==FNR{if(NF==2)a[$1];else a[$1$2$3]

  7.                  }

  8. NR>FNR{

  9.             for(i in a) {

  10.             if (split(i,b,"/")>1)

  11.                    {if(($NF==b[1])||($NF==b[2]))print b[1]" / "b[2]"\t"$NF}

  12.            else  {if(($NF==i))print i"\t"$NF}
  13.                      
  14.                         }

  15.       }
复制代码

用法:awk -f test.awk book3 book3
我用的是gawk ,估计一般的awk都可以吧,这里没有什么特殊的函数。只有一个split。
我处理的时候,book3的规则是:第一列内若是没单元格的,第一列第二列直接tab隔开,
第一列内有单元格的,第一列内abcd / efgh (空格,/,空格)然后tab隔开然后再第二列。
按照这个规则的文件,这个脚本没问题。取前990行结果如下:
BRMS1L  BRMS1L
RPS6KA5 RPS6KA5
AP2B1   AP2B1
ARID4A  ARID4A
BTG3    BTG3
RBL1    RBL1
ARL1    ARL1
NAGK    NAGK
HBP1    HBP1
CDC37L1 CDC37L1
ERBB3   ERBB3
MAP3K5  MAP3K5
DCBLD2  DCBLD2
ANKRD13C / DKFZP566D1346        ANKRD13C
BTBD7   BTBD7
CTSA / PPGB     CTSA
C9orf5  C9orf5
CDKN1A  CDKN1A
PAFAH2  PAFAH2
SLC2A4  SLC2A4
APPL1 / APPL    APPL1
SLC30A7 SLC30A7
NRSN1 / VMP     NRSN1
PAPOLA  PAPOLA
PRR16 / LOC51334        PRR16
TUSC2   TUSC2
MTF1    MTF1
EIF2S1  EIF2S1
PLAGL2  PLAGL2
CENPO / MGC11266        CENPO
LAPTM4A LAPTM4A
PPP2CA  PPP2CA
EIF4H / WBSCR1  EIF4H
CEP57 / PIG8    CEP57
APP     APP
MAP3K14 MAP3K14
FZD7    FZD7
ABHD2   ABHD2
MBTPS1  MBTPS1
CTDSPL2 / HSPC129       CTDSPL2
UGDH    UGDH
至于3000行都是小case了,我处理过7000多行的文件也是shell ,很快的。
PS:你的附件的991行后数据都有问题
你给的几个数据我都试过了没问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP