使用perl将数据从一个制表符分隔的文件解析到另一个文件中
我有这样一个制表符分隔的文件(在我的脚本DIVERGE中): 我还有第二个以制表符分隔的文件,如下所示(数据): 我正在尝试将第一个文件中的第二列和第三列添加到第二个文件中,以便我可以(输出): 这是我正在尝试使用的perl脚本(尝试修改我在这里找到的脚本-对于perl来说非常新):使用perl将数据从一个制表符分隔的文件解析到另一个文件中,perl,text-processing,tab-delimited-text,Perl,Text Processing,Tab Delimited Text,我有这样一个制表符分隔的文件(在我的脚本DIVERGE中): 我还有第二个以制表符分隔的文件,如下所示(数据): 我正在尝试将第一个文件中的第二列和第三列添加到第二个文件中,以便我可以(输出): 这是我正在尝试使用的perl脚本(尝试修改我在这里找到的脚本-对于perl来说非常新): #/usr/bin/env/perl 严格使用; 使用警告; #打开正交重叠列表 打开(发散,“$ARGV[0]”)或关闭“使用重叠对打开输入文件时出错”; #散列以存储重叠ID 我的($espr,$liya,$D
#/usr/bin/env/perl
严格使用;
使用警告;
#打开正交重叠列表
打开(发散,“$ARGV[0]”)或关闭“使用重叠对打开输入文件时出错”;
#散列以存储重叠ID
我的($espr,$liya,$DISFENCE)=分割(“\t”,美元);
#通读正交重叠列表并读入内存
while(){
chomp$##摆脱结束白空间
($espr,$liya,$DISFESSION)->{$}=1;
}
关闭(分流);
#打开输出文件
打开(OUT“>$ARGV[2]”)或死“打开输出文件时出错”;
#打开数据文件
打开(数据“$ARGV[1]”)或死“打开序列对文件时出错\n”;
while(){
大口大口;
my($contigs、$FPC、$GOslim、$slimdesc、$GOterm、$GOdesc)=拆分(“\t”、$);
if(定义为$espr->{$contigs}){
打印出“$\”、“\t$liya\t$disference”、“\n”;
}
}
关闭(数据);
收尾;
但是我得到了一个错误,在第15行中无用地使用了私有变量,在第10行中使用了单位化值。我对perl术语/变量只有非常基本的掌握。因此,如果有人能指出我哪里出了问题以及如何解决,我将不胜感激。我会做什么:
#!/usr/bin/env perl
use strict; use warnings;
open my $fh1, "<", "file1" or die $!;
open my $fh2, "<", "file2" or die $!;
my %hash;
while (<$fh1>) {
chomp;
my @F = split;
$hash{$F[0]} = join "\t", @F[1..2];
}
while (<$fh2>) {
chomp;
my @F = split;
print join("\t", $_, $hash{$F[0]}), "\n";
}
close $fh1;
close $fh2;
这(如果我正确理解您的意图)可以通过以下命令在一行中完成(至少在Linux中):
这是一个使用本模块的机会。当然,对csv数据使用适当的解析器的好处是避免边缘案例破坏数据
use strict;
use warnings;
use Text::CSV;
my $div = "diverge.txt"; # you can also assign dynamical names, e.g.
my $data = "data.txt"; # my ($div, $data) = @ARGV
my $csv = Text::CSV->new({
binary => 1,
eol => $/,
sep_char => "\t",
});
my %div;
open my $fh, "<", $div or die $!;
while (my $row = $csv->getline($fh)) {
my $key = shift @$row; # first col is key
$div{$key} = $row; # store row entries
}
close $fh;
open $fh, "<", $data or die $!;
while (my $row = $csv->getline($fh)) {
my $key = $row->[0]; # first col is key (again)
push @$row, @{ $div{$key} }; # add stored values to $row
$csv->print(*STDOUT, $row); # print using Text::CSV's method
}
请注意,输出看起来不同,因为它是以制表符分隔的,而在问题中它是以空格分隔的。这里有另一个选项:
use strict;
use warnings;
my $data = pop;
my %diverge = map { /(\S+)\t+(.+)/; $1 => $2 } <>;
push @ARGV, $data;
while (<>) {
chomp;
$_ .= "\t$diverge{$1}\n" if /(\S+)/ and $diverge{$1};
print;
}
你对这条线有什么期待<代码>($espr,$liya,$DISFENCE)->{$}=1代码>当您
chomp$代码>无需指定$\uuu
。这就是为什么存在$\uu
。你可以说chomp
@sputnick-hmm..我从一个简单的脚本中获取了这一点,该脚本在一列中获取了一个值列表,以从第二个文件中提取具有多列的行-我在这里尝试做相同的操作,除了第一个文件具有多个列-我实际上不理解它的含义,只是尝试适应它situation@AndyLester谢谢那么我是否也应该从拆分中删除“$”?是的,您可以从split
中删除$\ucode>。不需要。未测试的代码<代码>$hash{$F[0]}=@F[1..2]
将该键上的值设置为2
。你的意思可能是[@F[1,2]]
或我的$key=shift@F$散列{$key}=\@F代码>@TLP我已经试过回答,是的,输出中只给出文件1的第3列。但TLP的第一个建议无法修复,第二个建议给出了错误全局符号“@F”需要显式的包名…@AmyEllison不,这是错误的。我的建议都解决了这个问题。如果他们没有,那是因为你做了我说的以外的事情。@AmyEllison哦,我明白了,他试图插值数组ref,好像它是一个数组。。。当然,打印应该是print join(“\t”、$\u、@{$hash{$F[0]}),“\n”
,这将非常简单,除了第一个文件第4列和第6列中的描述可以有空格。join的输出仅以空格分隔,因此无法将文件放回以制表符分隔的列中。join-t\t DATA DIVERGE如何?对我有用。
#!/usr/bin/env/perl
use strict;
use warnings;
#open the ortholog contig list
open (DIVERGE, "$ARGV[0]") or die "Error opening the input file with contig pairs";
#hash to store contig IDs
my ($espr, $liya, $divergence) = split("\t", $_);
#read through the ortho contig list and read into memory
while(<DIVERGE>){
chomp $_; #get rid of ending whitepace
($espr, $liya, $divergence)->{$_} = 1;
}
close(DIVERGE);
#open output file
open(OUT, ">$ARGV[2]") or die "Error opening the output file";
#open data file
open(DATA, "$ARGV[1]") or die "Error opening the sequence pairs file\n";
while(<DATA>){
chomp $_;
my ($contigs, $FPC, $GOslim, $slimdesc, $GOterm, $GOdesc) = split("\t", $_);
if (defined $espr->{$contigs}) {
print OUT "$_", "\t$liya\t$divergence", "\n";
}
}
close(DATA);
close(OUT);
#!/usr/bin/env perl
use strict; use warnings;
open my $fh1, "<", "file1" or die $!;
open my $fh2, "<", "file2" or die $!;
my %hash;
while (<$fh1>) {
chomp;
my @F = split;
$hash{$F[0]} = join "\t", @F[1..2];
}
while (<$fh2>) {
chomp;
my @F = split;
print join("\t", $_, $hash{$F[0]}), "\n";
}
close $fh1;
close $fh2;
contig04730 F GO:0000228 nuclear GO:0000783 telomere_cap contigK02622 0.3515
contig04730 F GO:0005528 reproduction GO:0001113 eggs contigK02622 0.3515
contig14757 P GO:0123456 immune GO:0003456 cells contigK03055 0.4
contig14757 P GO:0000782 nuclear GO:0001891 DNA_binding contigK03055 0.4
contig14757 C GO:0000001 immune GO:00066669 more_cells contigK03055 0.4
$ cat DATA
contig04730 F GO:0000228 nuclear GO:0000783 telomere_cap
contig04730 F GO:0005528 reproduction GO:0001113 eggs
contig14757 P GO:0123456 immune GO:0003456 cells
contig14757 P GO:0000782 nuclear GO:0001891 DNA_binding
contig14757 C GO:0000001 immune GO:00066669 more_cells
$ cat DIVERGE
contig04730 contigK02622 0.3515
contig04733 contigK02622 0.3636
contig14757 contigK03055 0.4
$ join DATA DIVERGE
contig04730 F GO:0000228 nuclear GO:0000783 telomere_cap contigK02622 0.3515
contig04730 F GO:0005528 reproduction GO:0001113 eggs contigK02622 0.3515
contig14757 P GO:0123456 immune GO:0003456 cells contigK03055 0.4
contig14757 P GO:0000782 nuclear GO:0001891 DNA_binding contigK03055 0.4
contig14757 C GO:0000001 immune GO:00066669 more_cells contigK03055 0.4
use strict;
use warnings;
use Text::CSV;
my $div = "diverge.txt"; # you can also assign dynamical names, e.g.
my $data = "data.txt"; # my ($div, $data) = @ARGV
my $csv = Text::CSV->new({
binary => 1,
eol => $/,
sep_char => "\t",
});
my %div;
open my $fh, "<", $div or die $!;
while (my $row = $csv->getline($fh)) {
my $key = shift @$row; # first col is key
$div{$key} = $row; # store row entries
}
close $fh;
open $fh, "<", $data or die $!;
while (my $row = $csv->getline($fh)) {
my $key = $row->[0]; # first col is key (again)
push @$row, @{ $div{$key} }; # add stored values to $row
$csv->print(*STDOUT, $row); # print using Text::CSV's method
}
contig04730 F GO:0000228 nuclear GO:0000783 telomere_cap contigK02622 0.3515
contig04730 F GO:0005528 reproduction GO:0001113 eggs contigK02622 0.3515
contig14757 P GO:0123456 immune GO:0003456 cells contigK03055 0.4
contig14757 P GO:0000782 nuclear GO:0001891 DNA_binding contigK03055 0.4
contig14757 C GO:0000001 immune GO:00066669 more_cells contigK03055 0.4
use strict;
use warnings;
my $data = pop;
my %diverge = map { /(\S+)\t+(.+)/; $1 => $2 } <>;
push @ARGV, $data;
while (<>) {
chomp;
$_ .= "\t$diverge{$1}\n" if /(\S+)/ and $diverge{$1};
print;
}
contig04730 F GO:0000228 nuclear GO:0000783 telomere_cap contigK02622 0.3515
contig04730 F GO:0005528 reproduction GO:0001113 eggs contigK02622 0.3515
contig14757 P GO:0123456 immune GO:0003456 cells contigK03055 0.4
contig14757 P GO:0000782 nuclear GO:0001891 DNA_binding contigK03055 0.4
contig14757 C GO:0000001 immune GO:00066669 more_cells contigK03055 0.4