3

I'm trying to read from a file the data that it contains and get 2 important pieces of data from the file and use it in a bash script. A string and then a number for example:

Box 12
Toy 85
Dog 13
Bottle 22

I was thinking I could write a while loop to loop through the file and store the data into a variable. However I need two different variables, one for the number and one for the word. How do I get them separated into two variables?

5
  • 1
    mywiki.wooledge.org/BashFAQ/001 Commented Jun 16, 2015 at 20:57
  • @Jahid, I note that you rolled back the "key/value" descriptor. Do you have a better way to make the question's title describe that we want to read more than one column at a time? If it doesn't have some kind of limitation to that effect ("multiple columns of data", maybe?), it's duplicative of many, many preexisting questions, and doesn't distinguish itself clearly to folks who are trying to find a question that fits what they're trying to do. Commented Jun 16, 2015 at 21:31
  • @CharlesDuffy Well, OP didn't say he wants key/value type data, that's the reason of rolling back, and yes it needs to be edited to be more specific... may be "storing space separated data ..." Commented Jun 16, 2015 at 21:36
  • "space-separated" could be just a single row being loaded into a single array. Unless you object, I'm going to go with "multiple columns of data" here. Commented Jun 16, 2015 at 21:45
  • @CharlesDuffy yap, that's perfect.. Commented Jun 16, 2015 at 21:56

3 Answers 3

1

Example code:

#!/bin/bash
declare -a textarr numarr
while read -r text num;do
textarr+=("$text")
numarr+=("$num")
done <file
echo ${textarr[1]} ${numarr[1]} #will print Toy 85

data are stored into two array variables: textarr numarr. You can access each one of them using index ${textarr[$index]} or all of them at once with ${textarr[@]}

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

1 Comment

The downside of this scheme (compared with an associative array) is that it is relatively hard to find the index that holds 'Dog' and from thence find that the number is 13. On the other hand, you can still answer the question 'if the number is 13, what is the name' which is relatively hard with the associative array.
1

To read all the data into a single associative array (in bash 4.0 or newer):

#!/bin/bash
declare -A data=( )
while read -r key value; do
   data[$key]=$value
done <file

With that done, you can retrieve a value by key efficiently:

echo "${data[Box]}"

...or iterate over all keys:

for key in "${!data[@]}"; do
  value=${data[$key]}
  echo "Key $key has value $value"
done

You'll note that read takes multiple names on its argument list. When given more than one argument, it splits fields by IFS, putting columns into their respective variables (with the entire rest of the line going into the last variable named, if more columns exist than variables are named).

Comments

0

Here I provide my own solution which should be discussed. I am not sure this is a good solution or not. Using while read construct has the drawback of starting a new shell and it will not be able to update a variable outside the loop. Here is an example code which you can modify to suite your own need. If you have more column data to use, then slight adjustment is need.

#!/bin/sh

res=$(awk 'BEGIN{OFS=" "}{print $2, $3 }' mytabularfile.tab)

n=0
for x in $res; do 
    row=$(expr $n / 2)
    col=$(expr $n % 2)
    #echo "row: $row column: $col value: $x"
    if [ $col -eq 0 ]; then
        if [ $n -gt 0 ]; then
            echo "row: $row "
            echo col1=$col1 col2=$col2
        fi
        col1=$x
    else
        col2=$x
    fi
    n=$(expr $n + 1)
done
row=$(expr $row + 1)
echo "last row: $row  col1=$col1 col2=$col2"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.