1

Thanks for your help in advance. I'm writing a simple bash script, which just read each line of a file, and then store each line into a different variable. For example, I'd like the script to perform the following commands:

d1=AER d2=BHR d3=CEF ... 

Therefore, I have a text file that has 10 lines, and each line is the content of the variables I'd like to store (e.g., AER), and I have the following test.sh script:

#!/bin/bash for i in {1..10..1} do $(d$i=$(sed -n ${i}p $HOME/textfile.txt)) done 

However,when executing the script, it gave me

./test.sh: line 4: d1=AER: command not found ./test.sh: line 4: d2=BHR: command not found ./test.sh: line 4: d3=CEF: command not found ... 

,instead of storing the characters into corresponding variables. Could somebody please identify where I did it wrong? Thank you so much!

3 Answers 3

6

The problem with your script is that if you need to interpolate a variable on the first line, bash thinks its the name of a program and tries to execute it. You can eval it, to make the variable:

eval "d$i=$(sed ...)" 

but its much simpler to use the read bash built-in, since it takes line input to a specified variable. Here's one way to do it:

for ((i=1;; i++)); do read "d$i" || break; done < textfile.txt echo "$d1" echo "$d2" 
Sign up to request clarification or add additional context in comments.

1 Comment

thanks a lot not only for the solution, but also the clear explanation!
4

Use an array, but the right way.

read -a d -d '\n' < textfile.txt echo "${d[1]}" 

Comments

0

As an alternative to the array solution, you can use eval.

((lnum=1)) exec 3< ${filetoread} while read -u3 line do eval `echo d${lnum}=\"${line}\"` ((lnum=1+${lnum})) done exec 3<&- 

6 Comments

Small comment - you can use self increment: let lnum++ or `((lnum++))``
Much better to use the declare command than eval: `declare d${lnum}="$line"
@chepner nice! (+1), I didn't realize/think-to declare/typeset/local to construct symbol names.
@twalberg something else that bugs me here is the FD... I mean I have used this before, but when you try to write reusable functions its kinda hard to know that you caller does not yet make use of FD#3
You can just redirect standard input for the loop--while read line; do ...; done < $filetoread--as long as the read command is the only thing in the loop that reads from standard input.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.