免费注册 查看新帖 |

Chinaunix

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

文件导入perl,处理,匹配,显示,用户输入等 perl新人求助 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-11-08 20:26 |只看该作者 |倒序浏览
这个是 代码中的dummy.pepmasses文件:

Protein                            pep   M/Z
YCL049C                   1     511.2465  0 0 MFSK
YCL049C                   2    4422.3098  0 0 YLVTASSLFVALTSAASTVDLDALLLLPGVESHDGVDTVFSTK
YCL049C                   3    1131.5600  0 0 DFYQVSFVK
YCL049C                   4    1911.0213  0 0 SIAPAIVNSSVIFHDVSR
YCL049C                   5     774.4059  0 0 GVAMGNVK
YCL049C                   6     261.1437  0 0 SR
YCL049C                   7    3122.3681  0 0 ASIFNPEETYYDWEQYQVVNNGDWR
YCL049C                   8    1433.6398  0 0 TEWAPASDCIWR
YCL049C                   9     404.1908  0 0 EEK
YCL049C                  10    1047.4104  0 0 DNSDETPDR
YCL049C                  11    3583.6053  0 0 FPISVPYNWTSQYSIVDYDTDANEDNLDFR
YCL049C                  12     406.2581  0 0 FIK
YCL049C                  13     574.3327  0 0 SLLDK
YCL049C                  14     146.1056  0 0 K

我自己的代码:
# !/user/bin/perl –w                        #指示perl的运行

$filename = “dummy.pepmasses”;    #filename指示

unless(open(IFILE,$filename)) {          #老师的PPT中是用的IFILE式,所以我也用的这个

           print “cannot open file\n”;       #如果打不开则输入cannot open

              exit;                                               #关闭
}
close IFILE


                                                        #这里好像缺了什么,在运行中filedata行报错,感觉像是将文件转化到@filedata的地方掉了


foreach my $line ( @filedata ){                                    #loop句法,上面缺失的部分应该已经将文件按行分割了

my @data = split (/\s+/, $line);                           #按列分割,因为中间有空格还不同,所以用的这个
}
print ‘What range of information do you want to know?’

到这里我就不会了,要求是如果使用者输入一个范围,然后上面的M/Z列的数字对这个范围进行匹配,然后在屏幕上显示或者输出在这个范围的所有行,并且在最后加上行数的计算。
比如使用者输入1000..5000
然后去除回车后匹配
2,3,4,7,8,10,11就匹配成功了,显示这些行,最后加一个print pepnumber=7 ,当然,估计最后的代码中这里可能是count或者另一个变量。

我是perl的新人,学了几个星期,感觉自己在这方面确实很弱,看了不少书小骆驼,24小时学perl,2个半小时学perl,perl实例精解,各种教程,还有perl本身的软件说明,perldoc,但是弄不成功。老师也觉得我很笨的样子。。。

希望有高手能够指点一下,这样子的代码大概是什么样子的,因为程序作业的最后期限将要到了,而我是我们组的最后一部分的完成者,不想拖后腿,即使完成了这个任务,我还是要在perl上继续走下去,只是情况紧急,所以来这里求助。谢谢大家的帮助!

论坛徽章:
0
2 [报告]
发表于 2015-11-09 00:40 |只看该作者
额。查看56,但是0回复,是我的问题有什么问题吗?

论坛徽章:
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
3 [报告]
发表于 2015-11-09 10:00 |只看该作者
本帖最后由 sunzhiguolu 于 2015-11-09 10:03 编辑

回复 2# alphafighter
问题有 2:
1.> 把您的代码从新整理一下, 把一些不必要的注释去除;
2.> 将您的问题部分精炼一下, 把 (有问题的部分 | 不明白的地方) 以代码的形式表现出来;

Perl 板块中 高手, 大神 非常多, 而且大家绝对都非常愿意帮助新手. (我像您一样也是新手)
欢迎来到 Perl 板块, 希望能够帮助到您...

   

论坛徽章:
6
丑牛
日期:2014-03-21 15:42:04子鼠
日期:2014-04-12 11:50:17处女座
日期:2014-09-01 09:25:1115-16赛季CBA联赛之吉林
日期:2015-12-22 14:01:5215-16赛季CBA联赛之广东
日期:2016-03-08 18:49:422016科比退役纪念章
日期:2016-07-06 12:19:55
4 [报告]
发表于 2015-11-09 14:56 |只看该作者
没人回?菜鸟来装一波。。。
  1. #!perl
  2. use strict;
  3. use warnings;

  4. my $filename = 'dummy.pepmasses';
  5. my $from     = 0;
  6. my $to       = 0;
  7. print "What range of information do you want to know ?\n";
  8. {
  9.     my $str = <STDIN>;
  10.     chomp $str;
  11.     ($from, $to) =  split /\.\./, $str;
  12. }

  13. # open file
  14. my $ifile_fh;
  15. open $ifile_fh, '<', $filename or
  16.     die "Cannot open file $filename: $!\n";

  17. # skip header
  18. readline $ifile_fh;

  19. my $prepnumber = 0;
  20. while (defined (my $line = <$ifile_fh>) ) {
  21.     # read each line in file
  22.     chomp $line;
  23.     my $mz_value = (split /\s+/, $line)[2];
  24.     if ($mz_value >= $from and $mz_value <= $to) {
  25.         # print matched line
  26.         print "$line\n";
  27.         ++$prepnumber;
  28.     }
  29. }
  30. print "prepnumber=$prepnumber\n" if $prepnumber;

  31. close $ifile_fh;

  32. __END__
复制代码

论坛徽章:
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
5 [报告]
发表于 2015-11-09 15:22 |只看该作者
回复 4# stanley_tam
readline $ifile_fh;

学习了...


   

论坛徽章:
0
6 [报告]
发表于 2015-11-09 22:58 |只看该作者
本帖最后由 alphafighter 于 2015-11-09 23:17 编辑

回复 4# stanley_tam

代码很厉害。不过代码里面的意义我不是很明白,请您帮我解释一下~

#!perl            
use strict;                                                
use warnings;   

my $filename = 'dummy.pepmasses';  这里为什么不先开始文件读取而是先开始输入?这是因为个人习惯还是这样有益程序运行?   
my $from     = 0;                                    
my $to       = 0;
print "What range of information do you want to know ?\n";
{
    my $str = <STDIN>;
    chomp $str;
    ($from, $to) =  split /\.\./, $str; 这里是user输入的区间,比如(10,100), 用户输入的是xx..xx这个split命令的作用怎么理解?
}

# open file
my $ifile_fh;
open $ifile_fh, '<', $filename or
    die "Cannot open file $filename: $!\n";

# skip header
readline $ifile_fh;

my $prepnumber = 0;
while (defined (my $line = <$ifile_fh>) ) {
    # read each line in file
    chomp $line;
    my $mz_value = (split /\s+/, $line)[2];    这句话的意思就是给一个变量赋予第二列的一个值?
    if ($mz_value >= $from and $mz_value <= $to) {      当这个if开始后,perl就会对每一行进行这个区间的比对,然后每个属于
        # print matched line                                              这个范围的行都会被打出来,这个if会不断重复直到读取完最后一行文件
        print "$line\n";                                                      是这样吗?
        ++$prepnumber;
    }
}
print "prepnumber=$prepnumber\n" if $prepnumber;       最后的这个 if $prepnumber是什么意思?

close $ifile_fh;

__END__


这个程序是一个大的程序的一部分。也就是说当用户输入完成一个值,程序返回一个值后,程序应该是等待用户输入下一个值或者进行到下一部分的,但是运行完一遍后每个变量里面都已经有了值。当close $ifile_fh运行的时候,所有的变量都被清零了吗?

如果我想增加一个功能,除了匹配完后输出匹配的行,所有匹配行的的M/Z值要全部加起来求一个平均数,应该怎么做?
这是我想的可能的代码:
my $prepnumber = 0;
my $summass = 0;
while (defined (my $line = <$ifile_fh>) ) {
    # read each line in file
    chomp $line;
    my $mz_value = (split /\s+/, $line)[2];   
    if ($mz_value >= $from and $mz_value <= $to) {      
        # print matched line                                             
        print "$line\n";                                                      
        ++$prepnumber;
        $summass = $mz_value+$summass;
    }
}
print "prepnumber=$prepnumber\n" if $prepnumber;      
print "average m/z number = $summass/$prepnumber\n";

close $ifile_fh;
这样对吗?
运行后最后报错 Use of uninitialized value $mz_value in numeric ge (>=) at 3.pl line 29, <$file_fh) line 423.
输出的结果正常。我运行的是 perl 5,version 22, subversion 0 (5.22.0) built for MSWin32-x64-multi-thread

还有在帖子内输入的这种带编号,灰色背景的代码是怎么做到的?
我拷贝了你的代码,但是粘贴在帖子上就变成了什么都没有的状态。

问题有点多哈。好不容易逮到个高手不容易啊 ^_^

论坛徽章:
6
丑牛
日期:2014-03-21 15:42:04子鼠
日期:2014-04-12 11:50:17处女座
日期:2014-09-01 09:25:1115-16赛季CBA联赛之吉林
日期:2015-12-22 14:01:5215-16赛季CBA联赛之广东
日期:2016-03-08 18:49:422016科比退役纪念章
日期:2016-07-06 12:19:55
7 [报告]
发表于 2015-11-10 09:28 |只看该作者
这里为什么不先开始文件读取而是先开始输入?这是因为个人习惯还是这样有益程序运行?  => 看你的需求貌似文件里的内容只用一次,就不打算文件读取存数组什么的了
用户输入的是xx..xx这个split命令的作用怎么理解? split的用法 =>  http://perldoc.perl.org/functions/split.html   或者发命令 perldoc -f split去看咯
  1. my $mz_value = (split /\s+/, $line)[2];    相当于:
  2. my @tmp = split /\s+/, $line;
  3. my $mz_value = $tmp[2];
复制代码
当这个if开始后,perl就会对每一行进行这个区间的比对,然后每个属于 ... => if在while里面,跟着while走的
当close $ifile_fh运行的时候,所有的变量都被清零了吗 => 每个变量都有自己的作用域,跟close $ifile_fh没有多大关系,例如变量$str到close这早就没有生存空间了
这样对吗? => 对或者不对,是2选1,试一次就得到答案了
Use of uninitialized value $mz_value in numeric ge  => 看报错,这个变量没有值,在文件的423行附近,打开文件看看,估计文件内容不是很格式化的



论坛徽章:
6
丑牛
日期:2014-03-21 15:42:04子鼠
日期:2014-04-12 11:50:17处女座
日期:2014-09-01 09:25:1115-16赛季CBA联赛之吉林
日期:2015-12-22 14:01:5215-16赛季CBA联赛之广东
日期:2016-03-08 18:49:422016科比退役纪念章
日期:2016-07-06 12:19:55
8 [报告]
发表于 2015-11-10 09:30 |只看该作者
  1. <code>
  2. 带编号,灰色背景的代码,点表情左边的<>按钮,输入内容。。
  3. </code>
复制代码

论坛徽章:
0
9 [报告]
发表于 2015-11-10 11:42 |只看该作者

  1. my $file = 'dummy.pepmasses';
  2. open my $IFILE, $file or die "cannot open file: $file\n";

  3. my ( $TITLE, @IFILE ) = map {
  4.     my ( undef, undef, $mz ) = split;
  5.     [ $mz, $_ ];
  6. } <$IFILE>;

  7. $TITLE = $TITLE->[1];
  8. my $QUIT = 0;

  9. until ($QUIT) {
  10.     print "What range of information do you want to know?\n";
  11.     print 'q: exit | ex: 300-500: ';

  12.     chomp( my $input = <> );
  13.     last if $input eq 'q';

  14.     my @range = split /\s*-\s*/, $input;

  15.     if ( @range != 2 ) {
  16.         print "ERROR INPUT!!\n";
  17.         next;
  18.     }

  19.     my ( $pepnumber, $summass ) = ( 0, 0 );

  20.     print "\n$TITLE";

  21.     for (@IFILE) {
  22.         my $mz = $_->[0];
  23.         if ( $range[0] <= $mz and $mz <= $range[1] ) {
  24.             print $_->[1];
  25.             $pepnumber++;
  26.             $summass += $mz;
  27.         }
  28.     }

  29.     print "\npepnumber = $pepnumber\n";
  30.     $pepnumber ||= 1;
  31.     print 'average   = ', $summass / $pepnumber, "\n\n";
  32. }

复制代码

论坛徽章:
0
10 [报告]
发表于 2015-11-10 21:36 来自手机 |只看该作者
非常感谢~
其实从我的需求来说,这些内容是需要无限次重复运行的,只要使用者需要查询不同范围内的值。
前辈说,可以使用一个另外的主程序来调用这个程序。或者也可以将本体做成可以重复运行的,这个是怎么做到的?

我需要将获得的内容,绘制成图。

我看了SVG绘图的例子,比对了下程序本来的要求,觉得有些难以实现。这个程序被要求,用户输入不同的范围,然后将输入的不同范围绘制成条形图。
X轴为不同的范围,比如用户输入的是 0..500+1000..2000+3000..5000
那么最后的输出结果就是X轴上是这四个范围的四个条,Y轴是这四个的M/Z平均值的标记。

这个代码怎么写?这个范围我从来没涉及过,感觉如果用户输入的值跟我设计的数量不一样,那我就得创造新的变量名,而且是程序自动的。这要如何做到?

如果能有代码自然好,我知道我的问题有点那啥。。。如果没有的话,能告诉我去哪能找到这个的答案,怎么搜索这个问题,有哪些关键词也好。。(估计我时间不够了。。)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP