Search code examples
arraysbashprintfecho

BASH scripting: Organizing output of a nested loop into a table


I have wasted so much of my time with this, I hope someone can help me. I am editing a script that is used to send values to an executable and then scrubs the output from the executable for tabulation. I have created two arrays that are filled with user inputted ranges, these ranges are then used to create a nested loop that I have put into a function (since I need to create 4 files from the output depending on another value). I admit that my code is abysmal, but it does the primary thing and that is obtaining the data I need and puts into the correct file. All I am trying to do is to get it to actually make a table with row and column labels, I just can't understand why this is so difficult. This is the problematic area:

# Function to loop user inputted ranges in order to generate report data.
function repeat()
{
    printf "%22s" 'density (10^18 m^-3)' 
    for a in "${density_array[@]}"  # for loop to list density values in the range set by the user.
    do
        printf "%13s" "$a"
    done
    echo -e "\n" 'speed (m/s)'
    #printf "%s\n" "${speed_array[@]}"
    for i in "${speed_array[@]}"
    do 
        echo "$i"
        for j in "${density_array[@]}"
        do
            echo $j > SCATINPUT     # generates a temporary file named SCATINPUT, with density value as first line.
            echo $temp >> SCATINPUT # appends a new line with temperature value to SCATINPUT file.
            echo $i >> SCATINPUT    # appends a new line with speed value to SCATINPUT file.
            echo $1 >> SCATINPUT    # appends a new line with rate type from argument to SCATINPUT file.

# pipes contents of SCATINPUT file to executable, extracts  value from STDOUT to RATE variable.
            RATE=`path_of_executable < SCATINPUT | awk '/0\./'` 

            RATEF=$(printf "%.4e" $RATE)    # converts number in RATE variable to scientific notation with 4 digits after decimal and sets RATEF variable.
            echo -ne "\t$RATEF"
            rm -f SCATINPUT # quietly deletes SCATINPUT file.
        done
    done
}

I am getting this output in a file:

density (10^18 m^-3)   2.0000e+00   4.0000e+00   6.0000e+00

speed (m/s)
8.0000e+06
7.6164e+04  1.4849e+05  2.1936e+059.0000e+06
5.7701e+04  1.1249e+05  1.6619e+051.0000e+07
4.3469e+04  8.4747e+04  1.2520e+051.1000e+07
3.3078e+04  6.4488e+04  9.5269e+041.2000e+07
2.5588e+04  4.9886e+04  7.3697e+04

But it should be this:

density (10^18 m^-3)   2.0000e+00   4.0000e+00   6.0000e+00

speed (m/s)
8.0000e+06             7.6164e+04   1.4849e+05  2.1936e+05
9.0000e+06             5.7701e+04   1.1249e+05  1.6619e+05
1.0000e+07             4.3469e+04   8.4747e+04  1.2520e+05
1.1000e+07             3.3078e+04   6.4488e+04  9.5269e+04
1.2000e+07             2.5588e+04   4.9886e+04  7.3697e+04

Solution

  • The general idea would be to replace the echo commands with comparable printf commands with formats that match the formats used to print the first/header line ...

    Start by replacing echo "$i" with printf "%22s" "$i" => this should leave the cursor on the same line as $i and lined up under the 2.0000e+00

    After you finish the j loop and before getting the next i do printf "\n" => this should move the cursor to the next line and ready for the next printf "%22s" "$i".

    That should get you started.

    If things don't line up quite right then consider replacing the echo -ne "\tRATEF" with a printf "%#s" "$RATEF" (adjust the number # to line up output as desired).