I have to calculate values from two files and store the result in output file. In the output file, each record shows the product of records with the same name in input files.

file one

s1 10
s2 20 
s3 25 
s4 25  
s5 25   
s6 20 
s7 25 
s8 25

file two

s2 4
s1 10
s3 2 
s4 3 
s6 3
s7 2
s8 2 


s1 100 
s2 80 
s3 50
s4 75 
s6 60 
s7 50 
s8 50

Note: I have to use a shell.

  • Go for a language like Ruby. – konsolebox Aug 7 '14 at 10:07
  • Is it homework?, if so then add homework tag, and tell us if there are any language constraints. – ctrl-alt-delor Aug 7 '14 at 10:11
  • Can you edit your own question: don't add amendments in comments, and have me edit the question. – ctrl-alt-delor Aug 7 '14 at 10:29
  • Why do you have to use the shell? Which shell do you have to use? Many shells (bash for example) can't deal with non integers. Is that an issue here? – terdon Aug 7 '14 at 10:38
  • 1
    Do you have to use only shell commands, or are commands like awk allowed. It would help if you post all the constraints in your question. – Mark Plotnick Aug 7 '14 at 14:59

This script does what you need. It assumes that your files are always in the format of

id value, id2 value2, id3 value3

That is, it assumes comma separated fields and a consistent format across both files. It also assumes a recent version of bash that supports indexed arrays. It also gives the correct output, that is the output you ask for and not the output you show (2x25 != 75 for example).

#!/usr/bin/env bash

## Read each line of the first file into the 
## array lines1.
mapfile -t lines1 < file1
## Do the same for the 2nd file and the array lines2.
mapfile -t lines2 < file2

declare -A fields2
declare -A fields1
## Iterate through each element of $lines2
## and separate ids from values
for ((i=0; i<${#lines2[@]}; i++)); do
    while read id val
    done < <(printf "%s\n" "${lines2[$i]//, /$'\n'}")

## Iterate through each element of $lines1, separate
## ids from values.
for ((i=0; i<${#lines1[@]}; i++)); do
    while read id val
        ## Some ids don't exist in both files, set their 
        ## value to 1 to avoid errors.
        if [[ -z "${fields2[$id]}" ]]; then
        ## Print the id and the result of the multiplication.
        printf "%s %d " $id  "$(( ${fields2[$id]} * $val ))";
    done < <(printf "%s\n" "${lines1[$i]//, /$'\n'}")
    echo "";

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.