Merge Two files of columns but insert columns of second file into columns of first file
You can use a loop in awk
, for example
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);}'
or
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);}'
The code assumes that the number of columns in awk
's input is even.
Use this Perl one-liner after paste
to print alternating columns:
paste file_A file_B | perl -F'\t' -lane 'print join "\t", @F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2 ];'
Example:
Create tab-delimited input files:
perl -le 'print join "\t", 1..5 for 1..2;' > file_Aperl -le 'print join "\t", "A".."E" for 1..2;' > file_Bhead file_A file_B
Prints:
==> file_A <==1 2 3 4 51 2 3 4 5==> file_B <==A B C D EA B C D E
Paste files side by side, also tab-delimited:
paste file_A file_B | perl -F'\t' -lane 'print join "\t", @F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2 ];'
Prints:
1 A 2 B 3 C 4 D 5 E1 A 2 B 3 C 4 D 5 E
The Perl one-liner uses these command line flags:-e
: Tells Perl to look for code in-line, instead of in a file.-n
: Loop over the input one line at a time, assigning it to $_
by default.-l
: Strip the input line separator ("\n"
on *NIX by default) before executing the code in-line, and append it when printing.-a
: Split $_
into array @F
on whitespace or on the regex specified in -F
option.-F'/\t/'
: Split into @F
on TAB, rather than on whitespace.
$#F
: last index of the array @F
with the input fields, split on tab.0 .. ( $#F - 1 ) / 2
: array of indexes of the array @F
, from the start (0) to half of the array. These are all indexes that correspond to file_A
.map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2
: map
takes the above array of indexes from 0 to half of the length of @F
, and returns a new array, with twice the number of elements. Its elements alternate: (a) the index corresponding to file_A
($_
) and (b) that index plus half the length of the array ($_ + ( @F/2 )
), which is the corresponding index from file_B
.@F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2 ]
: a slice of array @F
with the specified indexes, namely alternating fields from file_A
and file_B
.
SEE ALSO:
perldoc perlrun
: how to execute the Perl interpreter: command line switchesperldoc perldata
: Slices
With one awk script parsing the files:
FNR==NR { rec[NR] = $0 next}{ split(rec[FNR], fields) for (i=1;i<=NF;i++) $i = fields[i] FS $i print}
Usage:
awk -f tst.awk file_A file_B