Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading variable name from txt file

Tags:

linux

bash

I want to read variable name from txt file in bash script.

For example

I run var="thanks" in terminal
I create file.txt and txt file contains $var
I create variable var2 in terminal. var2=""
Then I run var2=$(<file.txt) command in terminal.

The Problem is

$ echo $var2
"$var"

I want the output of the echo $var command to be "thanks"

$ echo $var2
"thanks"

So what should I do?

like image 551
ofbahar Avatar asked Feb 28 '26 06:02

ofbahar


2 Answers

If you put just var into the file without the $ and quotes, you can use variable indirection.

var2=$(< file.txt)
var2=${!var2}
echo $var2

Or, if you need the dollar sign and quotes, remove them using parameter expansion before applying the indirection

var2=$(< file.txt)
var2=${var2#'"$'}
var2=${var2%\"}
var2=${!var2}
echo $var2
like image 106
choroba Avatar answered Mar 03 '26 04:03

choroba


Two different bash way for this:

1. Using ${!var} indirect expansion:

Anoter way for dropping $" if present:

IFS='$"' read -a var2 <file.txt
var2=(${var2[*]})
echo ${!var2}

Tests:

var=Hello\ world\!
echo '"$var"' >file.txt
cat file.txt 
"$var"

IFS='$"' read -a var2 <file.txt
var2=(${var2[*]})
echo ${!var2}
Hello world!

echo 'var' >file.txt 
cat file.txt 
var

IFS='$"' read -a var2 <file.txt
var2=(${var2[*]})
echo ${!var2}
Hello world!

Explanation:

  • IFS Input Field Separator (usually contain: $' \t\n' <space><tab><newline>). All characters in this field are treated as field separator, so don't appear in array.

  • IFS='..' read .. when variable definition prepend command, variable are only affected for this execution

  • -a var2 read make var2 an array. Use declare -p to show his content:

     IFS='$"' read -a var2 <file.txt
     declare -p var2
     declare -a var2=([0]="" [1]="" [2]="var")
    
  • ${var2[*]} will merge var's fields in a single string, separated by 1st $IFS character.

     echo "<${var2[*]}>"
     <  var>
    
  • var2=( foo bar baz ) will redefine var2 ignoring spaces (as any characters in $IFS)

     var2=(${var2[*]})  # This step become useless, in 2nd case, but harmless.
     declare -p var2
     declare -a var2=([0]="var")
    
  • ${!var2} is known as indirect expansion

     echo ${!var2}
     Hello world!
    

2. Using reference name: nameref

  • declare -n name=value make NAME a reference to the variable named by its value

IFS='$"' read -a var2 < file.txt
var2=(${var2[*]})
declare -p var2
declare -a var2=([0]="var")

declare -n var3=$var2
echo $var3
Hello world!

This is usefull as local -n in a function:

readFrom() {
    local var2
    IFS='$"' read -a var2 < $1
    var2=(${var2[*]})
    local -n target=$var2
    echo $target
}

Then

echo '"$var"' >file.txt
var=Hello\ world\!
readFrom file.txt 
Hello world!

Alternative to avoid forks when populating variables:

readFrom() {
    local var2
    IFS='$"' read -a var2 < $1
    var2=(${var2[*]})
    local -n target=$var2 result=${2:-INPUT}
    result=("$target")
}

Then

readFrom file.txt newvar
echo "$newvar"
Hello world!

Advantage of this:

  • you could populate any kind of variables like array of associative arrays
  • you could populate many variables in same function
like image 40
F. Hauri Avatar answered Mar 03 '26 05:03

F. Hauri



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!