1

i have two input files like this
file 1

 a  1 
 b  2 
 c  3 
 d  4 

file 2

 a
 a
 b
 c
 c
 c
 d 
 d

how can i create a shell script to have the following output

 a  1 
 a  1 
 b  2 
 c  3 
 c  3 
 c  3 
 d  4 
 d  4

I have tried the paste method and that will only paste the corresponding numbers in order not matching the alphabet. any kinda guidance is appreciated.

2

Assuming that both files are sorted on the first column:

$ join file1 file2
a 1
a 1
b 2
c 3
c 3
c 3
d 4
d 4

The join utility performs a relational INNER JOIN operation on its two input files. By default, the first column is the join column, and the input needs to be sorted on this column.

1

With awk, reading the first file into an array and printing from that based on the second file. The inputs don't need to be sorted here:

$ awk 'FNR==NR { a[$1] = $2; next } { print $1, a[$1] }' file1 file2
a 1
a 1
b 2
c 3
c 3
c 3
d 4
d 4
  • this doesn't display anything nor can i output to a file. – Vineeth Thomas Mar 21 at 14:56
  • @VineethThomas, it works for the sample inputs you showed, if they're stored in files named file1 and file2 in the current directory. You can store the output in a file with the usual output redirection > outputfile – ilkkachu Mar 21 at 14:59
0

I don't think you really need shell script for this, but if you want (e.g. if you don't have join, grep, etc), this one is only-builtin needed:

#you should not have spaces in start of file1.txt or file2.txt
search_first_col(){ 
         while read -r col nextcol ; do 
            case $col in "$1") 
                    echo "$col $nextcol" ;; 
            esac 
         done 
       }
while IFS= read -r lin ; do 
       search_first_col "$lin" </tmp/file1.txt
done </tmp/file2.txt
  • Ignoring the issue that this launches grep for each line of file2, you probably want to lock the pattern to start of line ^ and to whitespace at the end to avoid matching on substrings. But you'll still get issues with fields that look like regular expression patterns. Or use grep -wF, but that might still match the second column of file1. – ilkkachu Mar 21 at 14:23
  • @Kusalananda, ah right, -w might work but it's still bad. (and not standard.) – ilkkachu Mar 21 at 14:28
  • join and grep are POSIX (though join isn't that commonly used, so there might be embedded systems without it. E.g. my Busybox doesn't have it...) – ilkkachu Mar 21 at 14:31
  • If you're going to do that while read thing, you might want to use while read -r key value; do if [ "$key" = "$1" ] ... ; done < file1 to handle the columns separately? – ilkkachu Mar 21 at 14:32
  • @ilkkachu adjusted as suggested. Can you test in your busybox? If not I think we can select the columns using for... – Luciano Andress Martini Mar 21 at 14:48
0

I have tried by below method and its worked fine

for i in `cat file1| awk '{print $1}'`; do h=`awk -v i="$i" '$1 == i{print $2}' file1`;awk -v i="$i" -v h="$h" '$1==i{print $0 " " h}' file2;done

output

for i in `cat file1| awk '{print $1}'`; do h=`awk -v i="$i" '$1 == i{print $2}' file1`;awk -v i="$i" -v h="$h" '$1==i{print $0 " " h}' file2;done
a 1
 a 1
 b 2
 c 3
 c 3
 c 3
 d  4
 d 4
0

with Miller (https://github.com/johnkerl/miller/releases)

mlr --nidx --fs " " join -j 1 -f file2 file2

you have

a 1
a 1
b 2
c 3
c 3
c 3
d 4
d 4

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.