3

I have two text files of the same length, in order: one of products, the other of comparison products. I'd like the output to be "product;comparison" for each line. Yes I could throw them in a spreadsheet and export as csv, but I'd like to understand how to do it in bash. The two files are supplied as arguments.

#!/bin/bash
file1="$1";
file2="$2";
separator=";";
while read -r product
do
  read -r comp < "$file2";
  echo $product $separator $comp >> temp.txt;
done < "$file1"
tr -d " " < temp.txt | sort > out.txt
rm temp.txt

This gives me all the products with the same comparison product! Eg

$: cat out.txt
product1;comp1
product2;comp1
product3;comp1

I'm obviously not reading the single line of the comp file properly - what am I doing wrong? How do I read a single line?

Escher
  • 513
  • 1
  • 7
  • 15
  • 3
    (1) @steeldriver showed you how to fix the problem, but he didn’t explain what the problem is: When you say `read -r comp < "$file2"` in a loop, each time you go through the loop, the shell opens `"$file2"`, reads a line from it, and closes it. It doesn’t remember its location in the file, so it always reads from the beginning. The answer (as steeldriver demonstrates) is to open `"$file2"` once and keep it open throughout the execution of the loop. – G-Man Says 'Reinstate Monica' Oct 03 '14 at 16:00
  • 1
    (2) You should quote all references to shell variables unless you have a good reason not to. (3) If you want to delete spaces from the existing products and comparison products, your use of `tr` is fine. But if you’re using it simply to remove the spaces before and after the semicolon, why not just say `echo "$product$separator$comp"` or even `echo "$product;$comp"`? (4) If you’re not doing any other output from the loop, you can bring the output redirection outside and say `while … do … echo … done > temp.txt`, or even eliminate the temporary file and say `while … do … echo … done | sort …`. – G-Man Says 'Reinstate Monica' Oct 03 '14 at 16:00

1 Answers1

4

If you really want to do it in bash, I'd suggest making use of the -u fd option to read from the two files simultaneously using numbered streams, e.g.

while read -r -u3 product; read -r -u4 comp; do 
  printf '%s;%s\n' "$product" "$comp"
done 3<products.txt 4<comps.txt

However, you could just use the paste utility

paste -d\; products.txt comps.txt
steeldriver
  • 78,509
  • 12
  • 109
  • 152