Unix join on multiple fields on two files [closed]

2020-04-11 13:53发布

问题:

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 7 years ago.

I have a two files

cat test1.txt

1|2|3|4

2|3|4|4

3|4|5|5

cat test2.txt

1|2|4|5

2|3|5|6

3|5|7|7

My output should be

1|2|3|4|4|5

2|3|4|4|5|6

Its like joining two files on fields 1 and 2 and get the values of 1,2,3,4 from file 1 and 3,4, from file 2.

Please help me with this?

回答1:

awk -F\| 'NR == FNR {
  f2[$1, $2] = $3 OFS $4
  next
  }
($1, $2) in f2 {
  print $0, f2[$1, $2]
  }' OFS=\| test2.txt test1.txt


回答2:

Hmm, that works for your example:

 sed 's/|/+/' t1.txt>$$.tmp;sed 's/|/+/' t2.txt|join -t \| -j 1 $$.tmp -|sed 's/+/|/';rm $$.tmp


回答3:

This also seems to work:

$ sed 's/|/\t/2' 1.txt > 1_1.txt; sed 's/|/\t/2' 2.txt > 2_1.txt;
$ join -j1 1_1.txt 2_1.txt | tr ' ' '|'
$ rm 1_1.txt 2_1.txt

A one-liner without temporary file creation (thanks to @dbaupp):

$ join -j1 <(sed 's/|/\t/2' 1.txt) <(sed 's/|/\t/2' 2.txt) | tr ' ' '|'


回答4:

Try doing this in perl

paste -d '|' file1.txt file2.txt |
    perl -F'\|' -lane '
        print join "|", @F[0..3,6,7] if $F[0] eq $F[4] and $F[1] eq $F[5]
    '

And in sh :

#!/bin/sh

paste -d '|' test1.txt test2.txt | while IFS='|' read a1 a2 a3 a4 a5 a6 a7 a8; do
    if [ $a1 -eq $a5 -a $a2 -eq $a6 ]; then
        echo "$a1|$a2|$a3|$a4|$a7|$a8"
    fi
done

OUTPUT

1|2|3|4|4|5
2|3|4|4|5|6


回答5:

Another solution:

awk -F "|" '{getline a < "file1"}NR==1{print a, $3, $4 "\n"}NR==3{print a, $3, $4}' OFS="|" file2

Result:

$ awk -F "|" '{getline a < "file1"}NR==1{print a, $3, $4 "\n"}NR==3{print a, $3, $4}' OFS="|" file2
1|2|3|4|4|5

2|3|4|4|5|6