1

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!

5
  • there are errors to this chunk of code which I have just posted. Commented Jan 25, 2012 at 13:44
  • What errors? If you add them to the question it will be easier for us to help you. Commented Jan 25, 2012 at 13:47
  • line 12: bookArray[Count]: cannot assign list to array member Commented Jan 25, 2012 at 13:50
  • error occurs in this line > bookArray[Count]=('$bTitle', '$bAuthor', '$bPrice', '$bQtyAvail', '$bQtySold') Commented Jan 25, 2012 at 14:06
  • bash does not have multi-dimensional arrays. If that's what you really, really want, use a language with more flexible data structures, such as Perl. Commented Jan 25, 2012 at 14:57

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

5 Comments

This is what I would do. You can't read a table into an array, only a row, so it only makes sense to extract one row at a time from the file... at which point you may as well process it directly. Incidentally, though, you probably want a while IFS=: read ... ; do ... done < <(grep ...) construct so variables inside the while are part of the rest of the script.
this is my first time writing a program for it. so forgive me, the above chunk of codes, which part of it should i replace with? do i still need the cut function?
@Andres You do not need the cuts at all. Using read with IFS=: does all of that work for you.
@sorpigal process substitution is a bashism which is sometimes handy, but the OP should be made aware that it is not portable. (portability usually doesn't become a problem until after you've written tens of thousands of lines of code and find yourself debugging them for bashisms!)
@WilliamPursell: The question was for Linux, hence bash.
2

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!

5 Comments

hi Dan Fego, so do I actually need to replace any of my codes with the ones you mentioned above? Sorry that this is my first time and I am quite unfamiliar and not used to the syntax of shell prog.
Hi Dan Fego, apparently I have tried to play around with my codes. but still it came up with errors.
apparently I have tried to play around with my codes. but still it came up with errors. I incorporated your codes into my function which should be activated if user inputs the choice from a menu. Below will be my function function(my function) { BEGIN { printf "%-22s %-16s %-14s %-15s %-13s %s\n", "Title", "Author", "Price", "Qty Avail.", "Qty Sold", "Total Sales" } { printf "%-22s %-16s %-14.2f %-15d %-13d %0.2f\n", substring=${$1:1:22}, substring{$2:1:16}, $3, $4, $5, {$3 * $5} } awk -F: -f BookDB.awk BookDB.txt } when i tried to run it it says bad substitution.
(the above.) The error stated : bad substitution along in this part of the code. >> substring=${$1:1:22} <<
@Andres The entire text of that first code block can be saved to books.awk, and then you can run it from the command line like in the second code block (awk -F: -f books.awk books). It's a replacement for your current code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.