1

I have a problem with my bash array I was trying to read the file however the array allocated it in array[1] instead of 0

#!/bin/bash
index=0
INPUT=BookDB.txt
OLDIFS=$IFS
IFS=:
i=0
book=()
[ ! -f $INPUT ] && { echo "$INPUT file not found"; exit 99; }
while read bookname author price quantity sold
do
#echo "BookName : $bookname"
#echo "Author : $author"
#echo "Price : $price"
#echo "Quantity : $quantity"
#echo "Sold : $sold"

    book+=("$bookname")
    author+=("$author")
    price+=("$price")
    quant+=("$quantity")
    sold+=("$sold") 

 done < $INPUT
 IFS=$OLDIFS



 # Use c style for loop
 # get total subscripts in an array
 total=${#book[*]}
 # 
 for (( i=0; i<=$(( $total -1 )); i++ ))
  do
   echo $i "${book[$i]} "
 done

 total=${#author[*]}
 # 
 for (( i=0; i<=$(( $total -1 )); i++ ))
 do
  echo  $i "${author[$i]} "
 done

Here is the output of the file

Book

0 Harry Potter - The Half Blood Prince 
1 The little Red Riding Hood 
2 Harry Potter - The Phoniex 
3 Harry Potter - The Deathly Hollow 
4 Little Prince 
5 Lord of The Ring 
6 Three Little Pig 
7 All About Ubuntu 
8 Catch Me If You Can 
9 Happy Day

Author

0  
1 J.K Rowling 
2 Dan Lin 
3 J.K Rowling 
4 Dan Lin 
5 The Prince 
6 Johnny Dept 
7 Andrew Lim 
8 Ubuntu Team 
9 Mary Ann 
10 Mary Ann 

Somehow the array for author[0] is empty

  • 5
    There's one namespace for scalar and array variables, and in bash and ksh, arrays just extend scalar variables. $author is ${author[0]}, author=x or read author is assigning to author[0]. Use different variable names in your read statement. – Stéphane Chazelas Jan 27 '14 at 13:08
  • 1
    BTW, you'd be better off using perl or awk for that rather than bash loops and arrays. – Stéphane Chazelas Jan 27 '14 at 13:38
2

book is initialized to the empty array by the line book=(), so during the first run through the loop book+=("$bookname") sets the first element of the array book (i.e. ${book[0]}) to the first book name.

author is used sometimes as an array and sometimes as a scalar. In ksh and bash, when an array is referenced using a scalar syntax (i.e. anything other than ${VAR[INDEX]}), the first element of the array is used. Assigning to the variable in a way other than VAR=…, such as via the read builtin, sets the first element of the array. Conversely, if an array is expected, a scalar variable is treated as a one-word array. Thus:

  • On the first run through the loop, author contains the string J.K Rowling, then author+=("$author") sets it to a two-element array containing J.K Rowling twice.
  • On the second run through the loop, read sets ${author[0]} to Dan Lin, then author+=("$author") appends Dan Lin, yielding the three-element array ('Dan Lin' 'J.K. Rowling' 'Dan Lin').
  • On the last run, read sees an empty line, so it sets $bookname, ${author[0]} and the others to an empty string.

To fix this, use a different name for the loop variables and for the arrays where you accumulate the data.

titles=()
authors=()
prices=()
quantities=()
sales=()
while read title author price quantity sold
do
    titles+=("$title")
    authors+=("$author")
    prices+=("$price")
    quantities+=("$quantity")
    sales+=("$sold") 
 done < $INPUT
  • If your bash is new enough, there's a readarray command. – Ricky Beam Jan 27 '14 at 21:57
  • @RickyBeam readarray doesn't break the line into fields, so I don't see how it's useful here. – Gilles Jan 27 '14 at 22:04
  • Depends on the final purpose of his script. I don't see where 5 arrays are necessary, but we don't know what the final produce is supposed to do. – Ricky Beam Jan 27 '14 at 22:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.