2

I'm trying to read from a file, that has multiple lines, each with 3 informations I want to assign to the variables and work with.

I figured out, how to simply display them each on the terminal, but can't figure out how to actually assign them to variables.

while read i
do
  for j in $i
  do
    echo $j
  done
done < ./test.txt

test.txt:

1 2 3
a b c

So I want to read the line in the outer loop, then assign the 3 variables and then work with them, before going to the next line.

I'm guessing I have to read the values of the lines without an inside loop, but I can't figure it out right now.

Hope someone can point me in the right direction.

Biffen
  • 6,249
  • 6
  • 28
  • 36
Miha
  • 43
  • 1
  • 1
  • 4
  • I assume the first line is values, and the second line is variable names? That's a bit unusual. – Charles Duffy Apr 18 '18 at 18:11
  • If Glenn is right and I overread your question, see [BashFAQ #1](http://mywiki.wooledge.org/BashFAQ/001) - *How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?* – Charles Duffy Apr 18 '18 at 18:31
  • Yeah sorry, I guess the test.txt wasnt the best choice. Should have stayed with numbers only to make clear, that everything is a value. – Miha Apr 18 '18 at 19:00
  • Related (if the original value is given as a string/variable): [How to split one string into multiple strings separated by at least one space in bash shell? - Stack Overflow](https://stackoverflow.com/questions/1469849/how-to-split-one-string-into-multiple-strings-separated-by-at-least-one-space-in) – user202729 Aug 15 '21 at 04:51

2 Answers2

5

I think all you're looking for is to read multiple variables per line: the read command can assign words to variables by itself.

while read -r first second third; do
    do_stuff_with "$first"
    do_stuff_with "$second"
    do_stuff_with "$third"
done < ./test.txt
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • Heh. I took the OP to want a=1, b=2, c=3, but that appears to have been overreading. – Charles Duffy Apr 18 '18 at 18:30
  • This is portable to POSIX `sh`, and (if you drop the `-r` option to `read`, after understanding the implications) all the way back to v7 Bourne shell. – tripleee Jul 12 '22 at 09:49
  • As an aside, in many situations you want to avoid this if you can, in favor of e.g. a simple `sed` or Awk script perhaps. See also [`while read` loop extremely slow compared to `cat`, why?](https://stackoverflow.com/questions/13762625/bash-while-read-loop-extremely-slow-compared-to-cat-why) – tripleee Nov 02 '22 at 10:07
0

The below assumes that your desired result is the set of assignments a=1, b=2, and c=3, taking the values from the first line and the keys from the second.


The easy way to do this is to read your keys and values into two separate arrays. Then you can iterate only once, referring to the items at each position within those arrays.

#!/usr/bin/env bash
case $BASH_VERSION in
  ''|[123].*) echo "ERROR: This script requires bash 4.0 or newer" >&2; exit 1;;
esac

input_file=${1:-test.txt}

# create an associative array in which to store your variables read from a file
declare -A vars=( )

{
  read -r -a vals               # read first line into array "vals"
  read -r -a keys               # read second line into array "keys"
  for idx in "${!keys[@]}"; do  # iterate over array indexes (starting at 0)
    key=${keys[$idx]}           # extract key at that index
    val=${vals[$idx]}           # extract value at that index
    vars[$key]=$val             # assign the value to the key inside the associative array
  done
} < "$input_file"

# print for debugging
declare -p vars >&2

echo "Value of variable a is ${vars[a]}"

See:

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441