user3164754
user3164754

Reputation: 215

Tabulate part of text file written by shell

I have a shell script that is writing(echoing) the output on an array to a file. The file is in the following format

The tansaction detials for today are 35 

    Please check the 5 biggest transactions below   

-----------------------------------------------------------------------------------


Client Name,Account Number,Amount,Tran Time
Michael Press,20484,602117,11.41.02
Adam West,164121,50152,11.41.06
John Smith,15113,411700,11.41.07
Leo Anderson,2115116,350056,11.41.07
Wayne Clark,451987,296503,11.41.08

And i have multiple such line.

How do i tabulate the names after ---? I tried using spaces while echoing the array elements. Also tried tabs. I tried using column -t -s options. But the text above the --- is interfering with the desired output.

The desired output is

The tansaction detials for today are 35 

    Please check the 5 biggest transactions below   

-----------------------------------------------------------------------------------


Client Name   Account Number   Amount  Tran Time
Michael Press 20484            602117  11.41.02
Adam West     164121           50152   11.41.06
John Smith    15113            411700  11.41.07
Leo Anderson  2115116          350056  11.41.07
Wayne Clark   451987           296503  11.41.08

The printing to a file is a part of a bigger script. So, i am looking for a simple solution to plug into this script. Here's the snippet from that script where i am echoing to the file.

echo "The tansaction detials for today are 35 " >> log.txt
echo "" >> log.txt
echo "  Please check the 5 biggest transactios below   " >> log.txt
echo "" >> log.txt
echo "-----------------------------------------------------------------------------------" >> log.txt
echo "" >> log.txt
echo "" >> log.txt
echo "Client Name,Account Number,Amount,Tran Time" >> log.txt
array=( `output from a different script` )
x=1
for i in ${array[@]}
do

        #echo "Array $x - $i"
        Clientname=$(echo $i | cut -f1 -d',')
        accountno=$(echo $i | cut -f2 -d',')
        amount=$(echo $i | cut -f3 -d',')
        trantime=$(echo $i | cut -f4 -d',')

echo "$Clientname,$accountno,$amount,$trantime" >> log.txt
(( x=$x+1 ))
done

Upvotes: 0

Views: 116

Answers (2)

David C. Rankin
David C. Rankin

Reputation: 84561

If I understand your question, in order to produce the output format of:

Client Name   Account Number   Amount  Tran Time
Michael Press 20484            602117  11.41.02
Adam West     164121           50152   11.41.06
John Smith    15113            411700  11.41.07
Leo Anderson  2115116          350056  11.41.07
Wayne Clark   451987           296503  11.41.08

You should use the output formatting provided by printf instead of echo. For example, for the headings, you can use:

printf "Client Name   Account Number   Amount  Tran Time\n" >> log.txt

instead of:

echo "Client Name,Account Number,Amount,Tran Time" >> log.txt

For writing the five largest amounts and details, you could use:

printf "%-14s%-17s%8s%s\n" "$Clientname" "$accountno" "$amount" "$trantime" >> log.txt

instead of:

echo "$Clientname,$accountno,$amount,$trantime" >> log.txt

If that isn't what you are needing, just drop a comment and let me know and I'm happy to help further.

(you may have to tweak the field widths a bit, I just did a rough count)


True Tabular Output Requires Measuring Each Field

If you want to insure that your data is always in tabular form, you need to measure each field width (including the heading) and then take the max of either the field width (or heading) to set the field width for your output. Below is an example of how that can be done (using your simulated other program input):

#!/bin/bash

ofn="log.txt"   # set output filename

# declare variables as array and integer types
declare -a line_arr hdg name acct amt trn tmp
declare -i nmx=0 acmx=0 ammx=0 tmx=0

# set heading array (so you can measure lengths)
hdg=( "Client Name"
      "Account Number"
      "Ammount"
      "Tran Time" )

## set the initial max based on headings
nmx="${#hdg[0]}"    # max name width
acmx="${#hdg[1]}"   # max account width
ammx="${#hdg[2]}"   # max ammount width
tmx="${#hdg[3]}"    # max tran width

{ IFS=$'\n'         # your array=( `output from a different script` )
line_arr=($(
cat << EOF
Michael Press,20484,602117,11.41.02
Adam West,164121,50152,11.41.06
John Smith,15113,411700,11.41.07
Leo Anderson,2115116,350056,11.41.07
Wayne Clark,451987,296503,11.41.08
EOF
)
)
}

# write heading to file
cat << EOF > "$ofn"
The tansaction detials for today are 35

    Please check the 5 biggest transactions below

-----------------------------------------------------------------------------------


EOF

# read line array into tmp, compare to max field widths
{ IFS=$','
for i in "${line_arr[@]}"; do
    tmp=( $(printf "%s" "$i") )
    ((${#tmp[0]} > nmx )) && nmx=${#tmp[0]}
    ((${#tmp[1]} > acmx )) && acmx=${#tmp[1]}
    ((${#tmp[2]} > ammx )) && ammx=${#tmp[2]}
    ((${#tmp[3]} > tmx )) && tmx=${#tmp[3]}
    name+=( "${tmp[0]}" )   # fill name array
    acct+=( "${tmp[1]}" )   # fill account num array
    amt+=( "${tmp[2]}" )    # fill amount array
    trn+=( "${tmp[3]}" )    # fill tran array
done
}

printf "%-*s  %-*s  %-*s  %s\n" "$nmx" "${hdg[0]}" "$acmx" "${hdg[1]}" \
"$ammx" "${hdg[2]}" "${hdg[3]}" >> "$ofn"
for ((i = 0; i < ${#name[@]}; i++)); do
    printf "%-*s  %-*s  %-*s  %s\n" "$nmx" "${name[i]}" "$acmx" "${acct[i]}" \
"$ammx" "${amt[i]}" "${trn[i]}" >> "$ofn"
done

(you can remove the extra space between each field in the final two printf statements if you only want a single space between them -- looked better with 2 to me)

Output to log.txt

$ cat log.txt
The tansaction detials for today are 35

    Please check the 5 biggest transactions below

-----------------------------------------------------------------------------------


Client Name    Account Number  Ammount  Tran Time
Michael Press  20484           602117   11.41.02
Adam West      164121          50152    11.41.06
John Smith     15113           411700   11.41.07
Leo Anderson   2115116         350056   11.41.07
Wayne Clark    451987          296503   11.41.08

Look things over and let me know if you have any questions.

Upvotes: 1

EA-Lille
EA-Lille

Reputation: 561

I'm not sure to understand everythings =P

but to answer this question :

How do i tabulate the names after ---?

echo -e "Example1\tExample2"

-e means : enable interpretation of backslash escapes

So for your output, I suggest :

echo -e "$Clientname\t$accountno\t$amount\t$trantime" >> log.txt

Edit : If you need more space, you can double,triple,... it

echo -e "Example1\t\tExample2"

Upvotes: 1

Related Questions