Andres
Andres

Reputation: 275

Bash Shell Programming Store Variables from Text File into Arrays

My program should be able to work this way.

Below is the content of the text file named BookDB.txt The individual are separated by colons(:) and every line in the text file should serve as a set of information and are in the order as stated below.

Title:Author:Price:QtyAvailable:QtySold

Harry Potter - The Half Blood Prince:J.K Rowling:40.30:10:50
The little Red Riding Hood:Dan Lin:40.80:20:10
Harry Potter - The Phoniex:J.K Rowling:50.00:30:20
Harry Potter - The Deathly Hollow:Dan Lin:55.00:33:790
Little Prince:The Prince:15.00:188:9
Lord of The Ring:Johnny Dept:56.80:100:38

I actually intend to 1) Read the file line by line and store it in an array 2) Display it

However I have no idea on how to even start the first one. From doing research online, below are the codes which I have written up till now.

#!/bin/bash

function fnReadFile()
{
while read inputline
do
 bTitle="$(echo $inputline | cut -d: -f1)"
 bAuthor="$(echo $inputline | cut -d: -f2)"
 bPrice="$(echo $inputline | cut -d: -f3)"
 bQtyAvail="$(echo $inputline | cut -d: -f4)"
 bQtySold="$(echo $inputline | cut -d: -f5)"
 bookArray[Count]=('$bTitle', '$bAuthor', '$bPrice', '$bQtyAvail', '$bQtySold')
Count = Count + 1
done
}

function fnInventorySummaryReport()
{
fnReadFile
echo "Title                  Author           Price          Qty Avail.      Qty Sold      Total Sales"
for t in "${bookArray[@]}"
do
echo $t
done
echo "Done!"
}

if ! [ -f BookDB.txt ] ; then #check existance of bookdb file, create the file if not exist else continue
touch BookDB.txt
fi

"HERE IT WILL THEN BE THE MENU AND CALLING OF THE FUNCTION"

Thanks to those in advance who helped!

Upvotes: 1

Views: 4817

Answers (2)

William Pursell
William Pursell

Reputation: 212634

Why would you want to read the entire thing into an array? Query the file when you need information:

#!/bin/sh

# untested code:

# print the values of any line that match the pattern given in $1

grep "$1" BookDB.txt |
while IFS=: read  Title Author Price QtyAvailable QtySold; do
  echo title = $Title
  echo author = $Author
done

Unless your text file is very large, it is unlikely that you will need the data in an array. If it is large enough that you need that for performance reasons, you really should not be coding this in sh.

Upvotes: 3

Dan Fego
Dan Fego

Reputation: 14034

Since your goal here seems to be clear, how about using awk as an alternative to using bash arrays? Often using the right tool for the job makes things a lot easier!

The following awk script should get you something like what you want:

# This will print your headers, formatted the way you had above, but without
# the need for explicit spaces.
BEGIN {
    printf "%-22s %-16s %-14s %-15s %-13s %s\n", "Title", "Author", "Price",
    "Qty Avail.", "Qty Sold", "Total Sales"
}

# This is described below, and runs for every record (line) of input
{
    printf "%-22s %-16s %-14.2f %-15d %-13d %0.2f\n",
    substr($1, 1, 22), substr($2, 1, 16), $3, $4, $5, ($3 * $5)
}

The second section of code (between curly braces) runs for every line of input. printf is for formatted output, and uses the given format string to print out each field, denoted by $1, $2, etc. In awk, these variables are used to access the fields of your record (line, in this case). substr() is used to truncate the output, as shown below, but can easily be removed if you don't mind the fields not lining up. I assumed "Total Sales" was supposed to be Price multiplied by Qty Sold, but you can update that easily as well.

Then, you save this file in books.awk invoke this script like so:

$ awk -F: -f books.awk books
Title                  Author           Price          Qty Avail.      Qty Sold      Total Sales
Harry Potter - The Hal J.K Rowling      40.30          10              50            2015.00
The little Red Riding  Dan Lin          40.80          20              10            408.00
Harry Potter - The Pho J.K Rowling      50.00          30              20            1000.00
Harry Potter - The Dea Dan Lin          55.00          33              790           43450.00
Little Prince          The Prince       15.00          188             9             135.00
Lord of The Ring       Johnny Dept      56.80          100             38            2158.40

The -F: tells awk that the fields are separated by colon (:), and -f books.awk tells awk what script to run. Your data is held in books.

Not exactly what you were asking for, but just pointing you toward a (IMO) better tool for this kind of job! awk can be intimidating at first, but it's amazing for jobs that work on records like this!

Upvotes: 2

Related Questions