does bash have arrays that i can push into and run a for loop against?

Hi

I have a bash script where i need to push some values into an array and when finished, run a for loop against that array for example

myfile

sausages|meat
beef| meat
carrot| veg
...
...
for LINE in `cat myfile`; do
   FOOD=`echo $LINE | cut -d\| -f1`
   TYPE=`echo $LINE | cut -d\| -f2`
    
    case $TYPE in 

    meat)
             <push $FOOD into an array called @MEAT or something>
    ;; 
    veg)
             <push $FOOD into an array called @VEG or something>
   ;;
   esac
done


for element in @MEAT; do
    echo "I really like the meat called $@MEAT"
done


for element in @VEG; do
    echo "I really like the vegetable called $@VEG"
done

I know what I have done here is a syntactically incorrect (and mixes perl and bash all over the place :-))

but is what im doing above possible ? i.e can I push into an array with an ever incrementing element number (that i dont have to define) and then can I run a 'for' loop against the whole array ?

Id also like to perform a count against elements in a bash array as well if thats possible ?

i.e. if count of elements is more than 1 then use plural words etc etc

i know how to do all of this in perl, but is it possible in bash?

any help would be greatly appreciated

Something like:
while IFS='|' read FOOD TYPE ; do
case $TYPE in
meat)
MEAT=( "${MEAT[@]}" "$FOOD" )
# MEAT[${#MEAT[@]}]="$FOOD" would work too (see below)
;;
veg)
VEG[${#VEG[@]}]="$FOOD"
;;
esac
done <myfile
for element in "${MEAT[@]}"; do
echo "I really like the meat called $element"
done
for element in "${VEG[@]}"; do
echo "I really like the vegetable called $element"
done

Or another solution:

#!/bin/bash
while read ; do
   FOOD=${REPLY%|*}
   TYPE=`echo ${REPLY#*|}`  # use echo to trim leading spaces
 
  case $TYPE in 
     meat)
        MEAT[${#MEAT[@]}]=$FOOD
     ;; 
     veg)
        VEG[${#VEG[@]}]=$FOOD
     ;;
  esac
done < myfile
 
for element in "${MEAT[@]}"; do
    echo "I really like the meat called $element"
done
 
for element in "${VEG[@]}"; do
    echo "I really like the vegetable called $element"
done

You might also find it useful to check out useless use of backticks. Unlike perl, you can't cram things of unlimited size into a shell variable or argument list, so your programs might start surprising you once the file grows beyond 64KB (or even 4KB on some systems). This is an operating system limit.

Instead, whenever you have

for LINE in `cat file`

you do

while read LINE
do
        ....
done < file

so you never need more than a line at a time stored in a variable. This also avoids creating an extra do-nothing process (cat).

You can even do token splitting with read like frans illustrated.

1 Like

thanks everyone for the great responses, really helpful