0

Example File

oj Orange Juice

10 100

A half gallon of orange juice.

This is what I did and it worked

while read -r simpleName itemName; do
        read currentQuantity maximumQuantity
        read description
    echo "Item Name: $itemName"
    echo "Simple Name: $simpleName"
    echo "Item Number: $itemNumber"
    echo "Qty: $currentQuantity/$maximumQuantity"
    echo "Description: $description"
done < $FILE

Note: Item number is prompted from the user prior to this and it determines which file to open.

This while loop correctly reads the file, stores the variables, and gives the desired output. The issue is, I used this same exact while loop two more times and it's not working. For some reason in the other two scenarios, simpleName and itemName are coming up blank, but the rest are working correctly.

Here's an example of where it is NOT working

#!/bin/bash

echo "" read -p "Enter an item number: " itemNumber echo ""

FILE="./data/${itemNumber}.item" date=date "+%Y-%m-%d %H:%M:%S"

if test -f $FILE; then

if test -f ./data/queries.log; then
    echo "DELETED: $date - $simpleName" >> ./data/queries.log
else
    > ./data/queries.log
    echo "DELETED: $date - $simpleName" >> ./data/queries.log
fi

while read -r simpleName itemName; do
    read currentQuantity maximumQuantity
    read description
done < $FILE

rm $FILE

echo "$simpleName was successfully deleted."

else echo "ERROR: item not found." fi

Here, the output comes out incorrectly as

was successfully deleted

So $simpleName is blank for some reason. I can't figure out why it works in the first instance but not this instance.

Note: Both instances are within separate script files.

I'm aware that there are simpler ways to do things, however, I'm restricted to very very basic commands, I am not allowed to use sed, awk, grep, find, pretty much just what you see below.

1 Answers1

0

read always assigns values to the variables, even if it doesn't see the expected delimiter and hence exits with a falsy status.

E.g.

$ (var=abcdef; 
   echo "      var=\"$var\"";
   read var;
   echo "ret=$? var=\"$var\"") < /dev/null
      var="abcdef"
ret=1 var=""

See also the idiom for processing a final incomplete line in a while read loop too: What does `while read -r line || [[ -n $line ]]` mean?

So, when you have this:

while read -r simpleName itemName; do
    read currentQuantity maximumQuantity
    read description
done < $FILE

a three-line input will first load all the variables, then try to read to simpleName and itemName again, trashing them. Or course this would also read the whole file, and e.g. a four-line input will leave all the variables empty.

I'm not sure what you want to do here, but perhaps something like this:

while    read -r simpleName itemName
      && read currentQuantity maximumQuantity
      && read description; do
    process one set of values ...
done < "$FILE"
ilkkachu
  • 138,973
  • Thank you, that put me on the right path. Knowing that it's trashing them at the end, basically means I need to do whatever I need to do with them, within the while loop, instead of afterwards. – PioneerRaptor Sep 19 '21 at 17:31
  • @PioneerRaptor, can the file actually even have more than those three lines? If not, you could just do { read && read && read; } < "$FILE" without the loop and use the variables directly. Or if know the file has blocks of three lines, you could use ... < <(tail -n3 "$FILE") to read the last three lines. (Which is not the same as looping over the triple read if the total number of lines isn't a multiple of three) – ilkkachu Sep 19 '21 at 17:38
  • In this instance, all files are exactly the same format and same amount of lines. So thank you for that. bash is a lot different than C and Java, seems like there are so many more ways to do things. – PioneerRaptor Sep 19 '21 at 17:40
  • 1
    @PioneerRaptor yeah, well, nobody sane does actual data processing in sh or bash because it's a terrible language for doing that. Instead, they do the processing in C, java, awk, perl, python, or whatever else (anything but shell) and merely use a shell script as a wrapper around the code that does the work. – cas Sep 20 '21 at 05:29