合并两个列文件,但将第二个文件的列插入第一个文件的列
Merge Two files of columns but insert columns of second file into columns of first file
假设两个文件的列数相同。
file_A:
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
和
file_B:
A B C D E
A B C D E
A B C D E
A B C D E
A B C D E
我想按顺序合并两个文件
file_C:
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
我在社区中找到了这样的解决方案
paste file_A file_B | awk '{print ,,,,,,,,,}'
但考虑到每个文件的列数大约为 100 或不是常量,我想知道是否有更好的方法。
提前致谢。
在 paste
之后使用此 Perl one-liner 打印交替列:
paste file_A file_B | perl -F'\t' -lane 'print join "\t", @F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2 ];'
示例:
创建 tab-delimited 个输入文件:
perl -le 'print join "\t", 1..5 for 1..2;' > file_A
perl -le 'print join "\t", "A".."E" for 1..2;' > file_B
head file_A file_B
打印:
==> file_A <==
1 2 3 4 5
1 2 3 4 5
==> file_B <==
A B C D E
A B C D E
并排粘贴文件,也tab-delimited:
paste file_A file_B | perl -F'\t' -lane 'print join "\t", @F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2 ];'
打印:
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
Perl one-liner 使用这些命令行标志:
-e
:告诉 Perl 查找代码 in-line,而不是在文件中。
-n
:一次循环输入一行,默认分配给 $_
。
-l
: 在执行代码 in-line 之前去除输入行分隔符(默认情况下在 *NIX 上为 "\n"
),并在打印时附加它。
-a
: 在空格或 -F
选项中指定的正则表达式上将 $_
拆分为数组 @F
。
-F'/\t/'
: 在 TAB 上拆分为 @F
,而不是在空格上。
$#F
: 包含输入字段的数组 @F
的最后一个索引,在选项卡上拆分。
0 .. ( $#F - 1 ) / 2
: 数组 @F
的 indexes 的数组,从开始 (0) 到数组的一半。这些都是对应file_A
.
的索引
map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2
: map
采用上述索引数组从 0 到 @F
长度的一半,returns 一个新数组,元素数量是其两倍。它的元素交替出现:(a) 对应于 file_A
($_
) 的索引和 (b) 该索引加上数组长度的一半 ($_ + ( @F/2 )
),这是来自的对应索引file_B
.
@F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2 ]
:具有指定索引的数组 @F
的切片,即来自 file_A
和 file_B
.
的交替字段
另请参见:
perldoc perlrun
: how to execute the Perl interpreter: command line switches
perldoc perldata
: Slices
您可以在 awk
中使用循环,例如
paste file_A file_B | awk '{
half = NF/2;
for(i = 1; i < half; i++)
{
printf("%s %s ", $i, $(i+half));
}
printf("%s %s\n", $half, $NF);
}'
或
paste file_A file_B | awk '{
i = 1; j = NF/2 + 1;
while(j < NF)
{
printf("%s %s ", $i, $j);
i++; j++;
}
printf("%s %s\n", $i, $j);
}'
代码假定 awk
输入中的列数是偶数。
用一个 awk 脚本解析文件:
FNR==NR {
rec[NR] = [=10=]
next
}
{
split(rec[FNR], fields)
for (i=1;i<=NF;i++) $i = fields[i] FS $i
print
}
用法:
awk -f tst.awk file_A file_B
假设两个文件的列数相同。
file_A:
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
和
file_B:
A B C D E
A B C D E
A B C D E
A B C D E
A B C D E
我想按顺序合并两个文件
file_C:
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
我在社区中找到了这样的解决方案
paste file_A file_B | awk '{print ,,,,,,,,,}'
但考虑到每个文件的列数大约为 100 或不是常量,我想知道是否有更好的方法。
提前致谢。
在 paste
之后使用此 Perl one-liner 打印交替列:
paste file_A file_B | perl -F'\t' -lane 'print join "\t", @F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2 ];'
示例:
创建 tab-delimited 个输入文件:
perl -le 'print join "\t", 1..5 for 1..2;' > file_A
perl -le 'print join "\t", "A".."E" for 1..2;' > file_B
head file_A file_B
打印:
==> file_A <==
1 2 3 4 5
1 2 3 4 5
==> file_B <==
A B C D E
A B C D E
并排粘贴文件,也tab-delimited:
paste file_A file_B | perl -F'\t' -lane 'print join "\t", @F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2 ];'
打印:
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
Perl one-liner 使用这些命令行标志:
-e
:告诉 Perl 查找代码 in-line,而不是在文件中。
-n
:一次循环输入一行,默认分配给 $_
。
-l
: 在执行代码 in-line 之前去除输入行分隔符(默认情况下在 *NIX 上为 "\n"
),并在打印时附加它。
-a
: 在空格或 -F
选项中指定的正则表达式上将 $_
拆分为数组 @F
。
-F'/\t/'
: 在 TAB 上拆分为 @F
,而不是在空格上。
$#F
: 包含输入字段的数组 @F
的最后一个索引,在选项卡上拆分。
0 .. ( $#F - 1 ) / 2
: 数组 @F
的 indexes 的数组,从开始 (0) 到数组的一半。这些都是对应file_A
.
的索引
map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2
: map
采用上述索引数组从 0 到 @F
长度的一半,returns 一个新数组,元素数量是其两倍。它的元素交替出现:(a) 对应于 file_A
($_
) 的索引和 (b) 该索引加上数组长度的一半 ($_ + ( @F/2 )
),这是来自的对应索引file_B
.
@F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2 ]
:具有指定索引的数组 @F
的切片,即来自 file_A
和 file_B
.
另请参见:
perldoc perlrun
: how to execute the Perl interpreter: command line switches
perldoc perldata
: Slices
您可以在 awk
中使用循环,例如
paste file_A file_B | awk '{
half = NF/2;
for(i = 1; i < half; i++)
{
printf("%s %s ", $i, $(i+half));
}
printf("%s %s\n", $half, $NF);
}'
或
paste file_A file_B | awk '{
i = 1; j = NF/2 + 1;
while(j < NF)
{
printf("%s %s ", $i, $j);
i++; j++;
}
printf("%s %s\n", $i, $j);
}'
代码假定 awk
输入中的列数是偶数。
用一个 awk 脚本解析文件:
FNR==NR {
rec[NR] = [=10=]
next
}
{
split(rec[FNR], fields)
for (i=1;i<=NF;i++) $i = fields[i] FS $i
print
}
用法:
awk -f tst.awk file_A file_B