从文件

时间:2018-02-12 15:28:02

标签: arrays perl

希望,有人可以帮我解决以下问题:

我有以下两个列表(一个是制表符分隔的):

chr \ t start \ t end \ t alt \ t ref \ t \ t *(其他列)

我的目标是使用perl脚本比较两个列表,基于colums中的值" start"," end"," alt"和" ref"。这意味着,如果这四个列中列表1中的行的值等于列表2的行中的条目,则列表1的整行应写入文件" common.txt"。对于基本脚本,我开始将列表1的内容写入数组:

#!/usr/local/bin/perl
use strict;
use warnings;

my @file1;
open (FILE, "< path_to_file") || die "Can not find file: $!\n";
while (defined(my $i = <FILE>) {
     push (@file1, $i)
     }
print "@file1\n"; #temporary added line to test for output 

结果,创建了一个包含FILE所有条目的数组@ file1(很好,该数组包含FILE的值)。现在的问题是:如何指定上面提到的列。我试图将数组写入标量$ content,并希望使用

隔离第二列(开始)
$content = @file1;
print "$content[1]\n";

但是(确实有道理),这些行给了我数组的元素[1],它是FILE的第二行。 合在一起:我使用while循环逐行将FILE的内容写入数组@ file1。如何提取定义的列的值? (注意:指定列的值未知,因此不能用于模式搜索)。

最佳, 脾气暴躁的

2 个答案:

答案 0 :(得分:1)

这是对两个文件进行并行迭代的更好方法:

use strict;
use warnings; 
use 5.020;
use autodie;
use Data::Dumper;

open my $INFILE1, '<', 'data1.txt';
open my $INFILE2, '<', 'data2.txt';
open my $OUTFILE, '>', 'common.txt';

while (!eof($INFILE1) and !eof($INFILE2)) {
    my $line1 = <$INFILE1>;
    my $line2 = <$INFILE2>;

    my(undef, $target1) = split ' ', $line1, 2;
    my(undef, $target2) = split ' ', $line2, 2;

    if ($target1 eq $target2) {
        print {$OUTFILE} $line1 
    }
}

close $INFILE1;
close $INFILE2;
close $OUTFILE;

请勿使用 bareword 文件句柄,例如文件。相反,使用my 变量:

open my $FILE, '<', 'data.txt'

从while循环中读取文件条件

while (my $line = <$FILE>)

perl会自动对defined()进行$line检查,而while循环只会在没有其他行读取且<>返回undef时结束。

不要试图通过阅读旧的perl教程来学习perl。相反,购买最新版的“Learning Perl”(Schwartz,d Foy,Phoenix)。 Perl拥有我研究的任何编程语言的最佳书籍,因此利用该资源。对于编程书来说,“学习Perl”相当薄,所以你不需要花一年的时间来阅读它。并且,它在每章末尾都有练习,并在本书的最后给出答案。

DATA1.TXT:

a 1 2 3 4
b 5 6 7 8
c 3 4 5 5
d 2 2 2 2

data2.txt:

w 2 4 2 4
x 5 6 7 8
y 3 4 5 6
z 2 2 2 2

代码:

use strict;
use warnings; 
use 5.020;
use autodie;
use Data::Dumper;

open my $INFILE1, '<', 'data1.txt';
open my $INFILE2, '<', 'data2.txt';
open my $OUTFILE, '>', 'common.txt';

LINE_FROM_FILE1:
while (my $line1 = <$INFILE1>) {
    if (defined(my $line2 = <$INFILE2>)) {
        my($first1, $target1) = split ' ', $line1, 2;
        my($first2, $target2) = split ' ', $line2, 2;

        if ($target1 eq $target2) {
            print {$OUTFILE} $line1 
        }
    }
    else {
        say "File2 is shorter than File1.  " .
            "No more lines in File2...quitting";
        last;
    }
}

close $INFILE1;
close $INFILE2;
close $OUTFILE;

输出:

$ rm common.txt
remove common.txt? y

$ perl 1.pl 

$ cat common.txt
b 5 6 7 8
d 2 2 2 2

答案 1 :(得分:0)

您想使用split访问每行的字段:

for my $line (@file1) {
    my @fields = split "\t", $line;  # split into fields with TAB as a delimiter
    print "$fields[1]\n";            # print second field of each line
}
如果你正在处理这样的分隔文件,那么

splitjoin应该很快成为你的perl词汇表的自然组成部分。