clb
clb

Reputation: 77

How to print output of two functions next to each in two columns--Bash script

I'm trying to create a bash script that calculates the average and median on rows and columns of a text file. I have the functions for the average and median working, however I'm trying to format the output for the rows (the column format is just fine).

This is what I want:

    Averages:   Medians:
    1           1
    5           5
    7           7
    5           6
    3           3
    6           6

However my output of code currently does this:

    Averages:   Medians:
    1
    5
    7
    5
    3
    6
    1
    5
    7
    6
    3
    6

The code I currently have is:

    if [[ $1 == -r* ]]
    then
        echo "Averages:    Medians"
        avg_nums $INPUT_FILE #calls average function on the file
        find_median $INPUT_FILE #calls median function
    elif... 
      #block of code for columns which works correctly.   
    fi

Another thing I've tried, which my teacher suggested, was storing the value of the average and median into a temp variable and then printing it all together when I was ready. It didn't work either. What I did for that was:

    #average function
    tempAvg+="$avg" #append the new value of average to a global var
    .
    .
    #median function
    tempMed+="${arr[$medIndex]}" #append the new value of median to a global var

and then calling it below

    if [[ $1 == -r* ]]
    then
        echo "Averages:    Medians"
        printf "%s\t%s\n" "$tempAvg" "$tempMed"
    elif... 
      #block of code for columns which works correctly.   
    fi

which gives an output of:

    Averages:    Medians:
    157536   157636

So obviously nothing I have tried has work. I'm new to bash scripting as well, just so you know. Does anyone have any suggestions on how to get this to work? Am I going about this the wrong way? Thanks.

edit: my input file is below (separated by tabs)

     1   1   1   1   1
     9   3   4   5   5
     6   7   8   9   7 
     3   6   8   9   7
     3   4   2   1   4
     6   4   4   7   7

Upvotes: 2

Views: 202

Answers (2)

David C. Rankin
David C. Rankin

Reputation: 84561

There are a number of way of approaching the problem. Thankfully, you are not looking for column sums and medians, which means you do not need to store all values for the duration of the script and can concentrate on row averages and row median, if I understood you correctly.

The average is, of course, easy, the median requires some form of sorting of the values row-wise to pick the median value. However, limiting to 3-columns, that is reasonably easy as well.

If you calculate and select the average and median for each row, you can then print the value immediately and accomplish your goals. You will want to print your header before you read and print the results for each line. One way to approach this would be similar to the following:

#!/bin/bash

printf "Averages:    Medians:\n"

while read -r c1 c2 c3 || [ -n "$c3" ]; do

    avg=$(( (c1 + c2 + c3)/3 ))   ## average row

    ## sort row
    [ $c1 -gt $c2 ] && { tmp=$c1; c1=$c2; c2=$tmp; }
    [ $c1 -gt $c3 ] && { tmp=$c1; c1=$c3; c3=$tmp; }
    [ $c2 -gt $c3 ] && { tmp=$c2; c2=$c3; c3=$tmp; }
    med=$c2  ## pick medain

    ## print the values in a sane format
    printf "  %3d         %3d\n" "$avg" "$med"

done <"$1"

exit 0

Input File

$ cat dat/rand10_3.txt
57      99      27
1       35      80
53      28      73
3       98      88
44      57      2
100     99      45
41      3       62
23      8       47
89      25      97
9       17      12

Use/Output

$ bash colavg3.sh dat/rand10_3.txt
Averages:    Medians:
   61          57
   38          35
   51          53
   63          88
   34          44
   81          99
   35          41
   26          23
   70          89
   12          12

Note: your averages will reflect the result of integer division, unless you pass the calculation to bc or something similar to do floating-point division.

Upvotes: 1

karakfa
karakfa

Reputation: 67507

You can use paste

paste <(avg_nums ...) <(find_medians ...) | sed '1i\Averages:\tMedians:'

Upvotes: 1

Related Questions