Perl 匹配模式后,将右侧的列附加到awk文件
我有两个文件,其中一个只是列向量,例如:Perl 匹配模式后,将右侧的列附加到awk文件,perl,bash,unix,scripting,awk,Perl,Bash,Unix,Scripting,Awk,我有两个文件,其中一个只是列向量,例如: 1x23 1y21 1z21 1z25 另一种是矩阵的形式 1x23 1x24 1y21 1y22 1y25 1z22 class 2000 3000 4000 5000 6000 7000 Yes 1500 1200 1100 1510 1410 1117 No 首先,我想找出第一个文件中的哪些行与第二个文件中的第一行相匹配。其次,我想复制第二个文件中与第一个文件中的列相匹配的列,并将它们附加到第二个文件中。因此,由于1x23,1x21匹配,我想复
1x23
1y21
1z21
1z25
另一种是矩阵的形式
1x23 1x24 1y21 1y22 1y25 1z22 class
2000 3000 4000 5000 6000 7000 Yes
1500 1200 1100 1510 1410 1117 No
首先,我想找出第一个文件中的哪些行与第二个文件中的第一行相匹配。其次,我想复制第二个文件中与第一个文件中的列相匹配的列,并将它们附加到第二个文件中。因此,由于1x23,1x21匹配,我想复制第二列中的这两列,并将其追加到类变量之前
我希望我的结果是正确的
1x23 1x24 1y21 1y22 1y25 1z22 1x23 1y21 class
2000 3000 4000 5000 6000 7000 2000 4000 Yes
1500 1200 1100 1510 1410 1117 1500 1100 No
我使用perl为3的循环编写代码,但由于数据非常大,它崩溃了。我认为应该有有效的方法来做到这一点 不确定Perl代码为何会崩溃。我建议在恒定内存中运行以下算法(在Perl中实现时可能比在AWK中更可读):
- 读取第一个文件并生成列名列表
- 读取数据文件的第1行(带实际标题)
- 将两个列表相交以生成列索引列表
- 读取数据文件的一行并按列拆分
- 通过使用步骤3中构建的“必需”列索引列表对列值进行索引,创建一个新的列值数组。输出它
- 重复最后2个步骤
- 读取第一个文件并生成列名列表
- 读取数据文件的第1行(带实际标题)
- 将两个列表相交以生成列索引列表
- 读取数据文件的一行并按列拆分
- 通过使用步骤3中构建的“必需”列索引列表对列值进行索引,创建一个新的列值数组。输出它
- 重复最后2个步骤
- 你可以试试
awk -f app.awk file1.txt file2.txt
其中,file1.txt
是您的第一个文件,file2.txt
是第二个文件,app.awk
是
NR==FNR {
key[$0]++
next
}
{
for (i=1; i<=NF; i++)
C[FNR,i]=$i
}
END {
for (i=1; i<=NF; i++)
if (C[1,i] in key)
k[++j]=i
nc=j
for (j=1; j<=FNR; j++) {
for (i=1; i<NF; i++)
printf "%s%s",C[j,i],OFS
for (i=1; i<=nc; i++)
printf "%s%s",C[j,k[i]],OFS
printf "%s%s",C[j,NF],RS
}
}
NR==FNR{
钥匙[$0]++
下一个
}
{
对于(i=1;i您可以尝试
awk -f app.awk file1.txt file2.txt
其中,file1.txt
是您的第一个文件,file2.txt
是第二个文件,app.awk
是
NR==FNR {
key[$0]++
next
}
{
for (i=1; i<=NF; i++)
C[FNR,i]=$i
}
END {
for (i=1; i<=NF; i++)
if (C[1,i] in key)
k[++j]=i
nc=j
for (j=1; j<=FNR; j++) {
for (i=1; i<NF; i++)
printf "%s%s",C[j,i],OFS
for (i=1; i<=nc; i++)
printf "%s%s",C[j,k[i]],OFS
printf "%s%s",C[j,NF],RS
}
}
NR==FNR{
钥匙[$0]++
下一个
}
{
对于(i=1;i,这里有一个冗长但不明确的方法
use strict;
use warnings;
open(my $data, '<', 'data.txt');
# read first row from the data file
my $line = <$data>;
chomp $line;
# create a list of columns
my @cols = split / /, $line;
# create hash with column indexes
my %colindex;
my $i = 0;
foreach my $colname (@cols) {
$colindex{$colname} = $i++;
}
# Save last column ('class')
my $lastcol = pop @cols;
# get input (column names)
open(my $input, '<', 'input.txt');
my @colnames = <$input>;
close $input;
# append column names to array if there is a match
foreach (@colnames) {
chomp;
if (exists $colindex{$_}) {
push @cols, $_;
}
}
# Restore the last column
push @cols, $lastcol;
# Now process your data
open(my $out, '>', 'output.txt');
# write the header column
print $out join(" ", @cols), "\n";
while ($line = <$data>) {
chomp $line;
my @l = split / /, $line;
foreach my $colname (@cols) {
print $out $l[$colindex{$colname}], " ";
}
print $out "\n";
}
close $out;
close $data;
使用严格;
使用警告;
打开(my$data,,'output.txt');
#写入标题列
打印$out join(“,@cols),“\n”;
而($line=){
chomp$行;
我的@l=拆分/,$line;
foreach我的$colname(@cols){
打印$out$l[$colindex{$colname}],“”;
}
打印$out“\n”;
}
收尾美元;
关闭$数据;
这里有一个冗长而清晰的方法
use strict;
use warnings;
open(my $data, '<', 'data.txt');
# read first row from the data file
my $line = <$data>;
chomp $line;
# create a list of columns
my @cols = split / /, $line;
# create hash with column indexes
my %colindex;
my $i = 0;
foreach my $colname (@cols) {
$colindex{$colname} = $i++;
}
# Save last column ('class')
my $lastcol = pop @cols;
# get input (column names)
open(my $input, '<', 'input.txt');
my @colnames = <$input>;
close $input;
# append column names to array if there is a match
foreach (@colnames) {
chomp;
if (exists $colindex{$_}) {
push @cols, $_;
}
}
# Restore the last column
push @cols, $lastcol;
# Now process your data
open(my $out, '>', 'output.txt');
# write the header column
print $out join(" ", @cols), "\n";
while ($line = <$data>) {
chomp $line;
my @l = split / /, $line;
foreach my $colname (@cols) {
print $out $l[$colindex{$colname}], " ";
}
print $out "\n";
}
close $out;
close $data;
使用严格;
使用警告;
打开(my$data,,'output.txt');
#写入标题列
打印$out join(“,@cols),“\n”;
而($line=){
chomp$行;
我的@l=拆分/,$line;
foreach我的$colname(@cols){
打印$out$l[$colindex{$colname}],“”;
}
打印$out“\n”;
}
收尾美元;
关闭$数据;
试试这一行:
awk 'NR==FNR{a[$0]=1;next}FNR==1{for(i=1;i<=NF;i++)if(a[$i])k[i]}{for(x in k)$NF= sprintf("%s ",$x) $NF}7' f1 f2
试试这一行:
awk 'NR==FNR{a[$0]=1;next}FNR==1{for(i=1;i<=NF;i++)if(a[$i])k[i]}{for(x in k)$NF= sprintf("%s ",$x) $NF}7' f1 f2
还有一个选择:
use strict;
use warnings;
my ( $matrix, @cols ) = pop;
my %headings = map { chomp; $_ => 1 } <>;
push @ARGV, $matrix;
while (<>) {
my @array = split;
@cols = grep $headings{ $array[$_] }, 0 .. $#array if $. == 1;
splice @array, -1, 0, @array[@cols];
print "@array\n";
}
使用向量文件中的条目创建散列。矩阵文件第一行上所有实体的列位置都保存在@col
中。将拆分
矩阵行中匹配的列条目插入到拆分
矩阵行的最后一个元素之前。最后,新行是print
ed
希望这有帮助!这里有另一个选项:
use strict;
use warnings;
my ( $matrix, @cols ) = pop;
my %headings = map { chomp; $_ => 1 } <>;
push @ARGV, $matrix;
while (<>) {
my @array = split;
@cols = grep $headings{ $array[$_] }, 0 .. $#array if $. == 1;
splice @array, -1, 0, @array[@cols];
print "@array\n";
}
使用向量文件中的条目创建散列。矩阵文件第一行上所有实体的列位置都保存在@col
中。将拆分
矩阵行中匹配的列条目插入到拆分
矩阵行的最后一个元素之前。最后,新行是print
ed
希望这有帮助