如何通过awk从一个文件中并排列的多个文件中输出数据?

how to output data from multiple files in side by side columns in one file via awk?

我有 30 个文件,名为 UE1.dat、UE2.dat .... 每个文件有 4 列。下面给出了 UE1.dat 和 UE2.dat.

的列结构示例

UE1.dat

1 4 2 1 
2 2 3 3
3 2 4 4   
4 4 4 2

UE2.dat

2 6 8 7 
4 4 9 6
7 1 1 2   
9 3 3 3

所以,我尝试了以下代码:

for((i=1;i<=30;i++)); do awk 'NR$i {printf ",";next} 1; END {print ""}' UE$i.dat; done > UE_all.dat

只从每个文件中获取第一列并将它们写入单个文件和并排的列,下面给出了所需的输出。

1 2
2 4
3 7
4 9

但不幸的是,代码将它们按行排序,你能给个提示吗?

提前致谢!

我可能会选择 - 使用 perl 而不是 awk,因为我更喜欢数据结构的处理。在这种情况下 - 我们使用二维数组,将每个文件的第一列插入到数组的新列中,然后打印整个内容。

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;

my $num_files = 2; 

my @rows;
my $count = 0; 
my $max = 0; 

for my $filenum ( 1..$num_files ) {
    open ( my $input, "<", "UE${filenum}.dat" ) or die $!;
    while ( <$input> ) {
        my @fields = split;
        push ( @{$rows[$filenum]}, $fields[0] );
        $count++;
    } 
    close ( $input ); 
    if ( $count > $max ) { $max = $count };
}

print Dumper \@rows;

for ( 0..$count ) { 
    foreach my $filenum ( 1..$num_files ) {
       print shift @{$rows[$filenum]} || ''," ";
    }
    print "\n";
}

在 awk 中你可以这样做:

1) 将此代码放入名为 output_data_from_multiple_files.awk:

的文件中
BEGIN {
    # All the input files are processed in one run.
    # filenumber counts the number of input files.
    filenumber = 1
}

{
    # FNR is the input record number in the current input file.
    # Concatenate the value of the first column in the corresponding
    # line in the output.
    output[FNR] = output[FNR] " " 

    # FNR == 1 means we are processing a new file.
    if (FNR == 1) {
        ++filenumber
    }
}

END {
    # print the output
    for (i=1; i<=FNR; i++)
        printf("%s\n", output[i])
}

2) 运行 awk -f output_data_from_multiple_files.awk UE*

所有文件都在 awk 的单次执行中处理。 FNR为当前输入文件中的输入记录号。 filenumber用于统计处理的文件数。输入文件中读取的值连接在 output 数组中。

我的解决方案是这样的

gawk 'BEGINFILE{f++}{print FNR,f,}' UE* | sort -nk 1,2 | cut -d" " -f3 | xargs -L $(ls UE*.dat | wc -l)

这就是我的方法...我使用 gawk 对行和文件进行编号,然后按行号对它们进行排序,然后按文件排序,只需使用 sort 并删除文件和行号。所以...

gawk 'BEGINFILE{f++}{print FNR,f,}' UE*

1 1 1  # line 1 file 1 is 1
2 1 2  # line 2 file 1 is 2
3 1 3  # line 3 file 1 is 3
4 1 4  # line 4 file 1 is 4
1 2 2  # line 1 file 2 is 2
2 2 4  # line 2 file 2 is 4
3 2 7  # line 3 file 2 is 7
4 2 9  # line 4 file 2 is 9

然后像这样使用sort把文件1的第一行接着文件2的第一行,文件n的第一行,文件1的第二行,文件2的第二行,第二个文件行 n。然后得到第三列:

gawk 'BEGINFILE{f++}{print FNR,f,}' UE* | sort -nk 1,2 | cut -d" " -f3
1
2
2
4
3
7
4
9

然后和xargs

一起放回去
gawk 'BEGINFILE{f++}{print FNR,f,}' UE* | sort -nk 1,2 | cut -d" " -f3 | xargs -L2
1 2
2 4
3 7
4 9

末尾的 -L2 必须与文件数匹配,即您的 -L30

使用 awk 关联数组将所有列连接到一个文件中:

# use a wildcard to get all the files (could also use a for-loop)
# add each new row to the array using line number as an index
# at the end of reading all files, go through each index (will be 1-4 in 
# your example) and print index, and then the fully concatenated rows
awk '{a[FNR] = a[FNR]" "[=10=]}END{ for (i in a) print i, a[i] | "sort -k1n"}' allfiles*