tags:

views:

437

answers:

6

I need to merge two files with a Bash script.

File_1.txt

TEXT01 TEXT02 TEXT03 TEXT04
TEXT05 TEXT06 TEXT07 TEXT08
TEXT09 TEXT10 TEXT11 TEXT12

File_2.txt

1993.0
1994.0
1995.0

Result.txt

TEXT01 TEXT02 1993.0 TEXT03 TEXT04
TEXT05 TEXT06 1994.0 TEXT07 TEXT08
TEXT09 TEXT10 1995.0 TEXT11 TEXT12

File_2.txt need to be merged at this specific position. I have tried different solutions with multiple do while loops, but they have not been working so far..

+5  A: 
awk '{
 getline s3 < "file1"
 printf "%s %s %s ",$1,$2,s3
 for(i=3;i<=NF;i++){
    printf "%s ",$i
 }
 print "" 
}END{close(s3)}' file

output

# more file
TEXT01 TEXT02 TEXT03 TEXT04
TEXT05 TEXT06 TEXT07 TEXT08
TEXT09 TEXT10 TEXT11 TEXT12
$ more file1
1993.0
1994.0
1995.0
$ ./shell.sh
TEXT01 TEXT02 1993.0 TEXT03 TEXT04
TEXT05 TEXT06 1994.0 TEXT07 TEXT08
TEXT09 TEXT10 1995.0 TEXT11 TEXT12
ghostdog74
Behold, the elegance of awk :)
Tim Post
+1  A: 

This is a solution without awk.
The interesting is how to use the file descriptors in bash.


#!/bin/sh
exec 5<test2.txt  # open file descriptor 5
cat test1.txt | while read ln
do
    read ln2 <&5 
        #change this three lines as you wish:
    echo -n "$(echo $ln | cut -d ' ' -f 1-2) "
    echo -n "$ln2 "
    echo $ln | cut -d ' ' -f 3-4 
done
exec 5>&-        # Close fd 5

Vereb
+1 for the file descriptor, -1 for useless use of cat. Also, doing two cuts inside a loop for each line of the input file could be really slow for a large file. I would use Bash's word-splitting instead.
Dennis Williamson
the echos can be changed to: array=( ${ln} ) echo "${array[0]} ${array[1]} $ln2 ${array[2]} ${array[3]}"
Vereb
you can also read into an array directory. read -a arr
ghostdog74
`s/directory/directly/` perhaps?
Dennis Williamson
A: 

Using perl, give file1 and file2 as arguments to:

#/usr/local/bin/perl

open(TXT2, pop(@ARGV));

while (<>) {
    chop($m = <TXT2>);

    s/^((\w+\s+){2})/$1$m /;

    print;
}
rsp
why is it chop and not chomp ?
ghostdog74
You will have to ask Larry Wall :-) Chop removes the newline (last char) of the line read into $m.
rsp
`chop` removes the last character, regardless of what it is. `chomp` removes a trailing newline but does nothing otherwise.
ephemient
ah, for scripting I tend to stick to the Perl 4 syntax :-)
rsp
+2  A: 

Why, use cut and paste, of course! Give this a try:

paste -d" " <(cut -d" " -f 1-2 File_1.txt) File_2.txt <(cut -d" " -f 3-4 File_1.txt)
Dennis Williamson
I added a variant of this
Vereb
+2  A: 

This was inspirated by Dennis Williamson's answer so if you like it give there a +1 too!

paste test1.txt test2.txt  | awk '{print $1,$2,$5,$3,$4}'
Vereb
+1: that's clever
Dennis Williamson
+1  A: 

Since the question was tagged with 'sed', here's a variant of Vereb's answer using sed instead of awk:

paste File_1.txt File_2.txt | sed -r 's/( [^ ]* [^ ]*)\t(.*)/ \2\1/'

Or in pure sed ... :D

sed -r '/ /{H;d};G;s/^([^\n]*)\n*([^ ]* [^ ]*)/\2 \1/;P;s/^[^\n]*\n//;x;d' File_1.txt File_2.txt
KirarinSnow