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?

  • 2
    (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 Oct 3 '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 Oct 3 '14 at 16:00
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

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.