0

I have a file.txt for example (it does not have the same number of columns for each row):

1 2 3 4
5 5 6 
7 7 7 7 9 10

I have another file (file2.txt) that contains 2 columns

    a b
    c d
    e f

I use this command:

awk '{print $1,$(cut -f2 file2.txt)}' file.txt > final.txt

I want to take the second column of file2.txt and add it between columns 1 and 2 of file1.txt.

Ex. of results:

1 d 2 3 4 
5 d 5 6
7 f 7 7 7 9 10

I want also maintaining all the remaining columns of file1.txt

3
  • Should that be a "b" on the first line of your desired results? Jul 4, 2019 at 14:38
  • Yes, sorry, it's a b
    – Will
    Jul 4, 2019 at 14:43
  • Then please edit your question to fix that typo. Also, does file2 really have leading whitespace? Jul 4, 2019 at 14:44

5 Answers 5

1

Pure awk:

awk '
    FNR==NR{c[NR]=$2}
    FNR!=NR{$1 = $1 OFS c[FNR]; print}
' file2 file

Output:

1 b 2 3 4 
5 d 5 6 
7 f 7 7 7 9 10
1
  • 1
    You could also write FNR != NR {$1 = $1 OFS c[FNR]; print} but that forces awk to rebuild $0. I don't know which would be faster. Jul 4, 2019 at 14:42
1

How about a little cut'n'paste?

paste -d" " <(cut -d" " -f1 file1.txt) <(cut -d" " -f2 file2.txt) <(cut -d" " -f2- file1.txt)
4
  • 1
    from OPs input, it must be -f6 for file2 ...
    – pLumo
    Jul 4, 2019 at 14:34
  • I don't understand your comment. "I have another file (file2.txt) that contains 2 columns" -- where does field 6 come from? Jul 4, 2019 at 14:38
  • 1
    I copy-pasted the example file which has 4 spaces in front, and cut does not ignore those. So first 4 fields are empty. Not sure if it was by purpose or unintended,
    – pLumo
    Jul 4, 2019 at 14:39
  • 1
    Oh I see that. I was assuming there is no leading space and edited that out on my system. Can replace middle cut with <(awk '{print $2}' file2.txt) Jul 4, 2019 at 14:40
0

While some implementations of awk do allow reading from piped sub-processes1, in this case I'd suggest reading the whole line from the second file, and doing the field splitting inside awk:

$ awk '(getline line < "file2.txt") > 0 {split(line,a); $1 = $1 FS a[2]} 1' file1.txt
1 b 2 3 4
5 d 5 6
7 f 7 7 7 9 10

Alternatively, you could consider using paste and cut, avoiding awk altogether


  1. see for example Using getline from a Pipe
0

With Perl, you read a line from file 1 then read a line from file2 via stdin. Afterwards stitch the lines in the desired order.

 $ perl -pale '$_ = join "\t", shift @F, <STDIN> =~ /\S\s+(\S+)/, @F' file1.txt < file2.txt

Output:

 1  b   2   3   4
 5  d   5   6
 7  f   7   7   7   9   10
0

Try with below command

awk 'FNR==NR{b[FNR]=$2;next}{print $1,b[FNR],$2,$3,$4,$5,$6,$7}' file2.txt  file1.txt 
1
  • 1
    The main problem here being that file.txt "does not have the same number of columns for each row" so hard-coding 7 fields is a limited solution.
    – Jeff Schaller
    Jul 9, 2019 at 11:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .