reading variables from input file bash - bash

I have an input file that looks like:
VAR1=1
VAR2=2
VAR3=3
VAR4=.T.
I'd like to read in these variables and define them as such. I've tried
while read line
do
exec $line
done < "Master.inp"
i've tried just
$line
instead, but that didn't work either. Is there a way to run the string as if I had just typed out the string in the bash file?

You can do it just sourcing the code:
. file
this will let you use the vars $VAR1, $VAR2, ...
Test
$ cat a
VAR1=1
VAR2=2
VAR3=3
VAR4=.T.
$ cat b
. a
echo $VAR1
$ ./b
1

Related

Expand matched strings in sed

Is it possible to expand the matched string in a sed command? I want to substitute variable names in a file with their values, this is my script at the moment:
#!/bin/bash
echo "Running the build script..."
VAR1="2005648"
VAR2="7445aa"
SERVER_NAME=$(hostname)
TIMESTAMP=$(date +%m-%d-%Y)
sed -i "s/{[A-Z_][A-Z_]*}/$&/g" my_file.txt #variable names in the file are written between { }
and this is a snapshot of my_file.txt:
Building finished at {TIMESTAMP}
{VAR1}:{VAR2}
On: {SERVER_NAME}
current working directory: {PWD}
But it doesn't work. Instead of substituting the variable name with it's value, It inserts a dollar sign right before the curly bracket.
How do I resolve this?
You could use envsubst to substitute environment variables, otherwise you would need a bunch of sed commands to replace everything.
Change your template file to:
Building finished at ${TIMESTAMP}
${VAR1}:${VAR2}
On: ${SERVER_NAME}
current working directory: ${PWD}
And the script to:
#!/bin/bash
echo "Running the build script..."
export VAR1="2005648"
export VAR2="7445aa"
export SERVER_NAME=$(hostname)
export TIMESTAMP=$(date +%m-%d-%Y)
# only replace the defined variables
envsubst '$VAR1 $VAR2 $SERVER_NAME $TIMESTAMP' < my_file.txt > newfile
# replace all environment variables ($USER, $HOME, $HOSTNAME, etc.)
#envsubst < my_file.txt > newfile.txt > newfile
The script replaces environment variables $VAR1, $VAR2, $SERVER_NAME and $TIMESTAMP in my_file.txt and saves the output to newfile.
You can see that ${PWD} doesn't get replaced, because I forgot to add it to the list.
In the second commented example all environment variables are replaced and non-existing variables are replaced by an empty string.
You can use the $VARNAME or ${VARNAME} syntax in the template.
I'd actually do it in a single pass this way using an awk that supports ENVIRON[], e.g. any POSIX awk:
$ cat tst.sh
#!/bin/env bash
echo "Running the build script..."
VAR1=2005648 \
VAR2=7445aa \
SERVER_NAME=$(hostname) \
TIMESTAMP=$(date +%m-%d-%Y) \
awk '
{
while ( match($0,/{[[:alnum:]_]+}/) ) {
printf "%s", substr($0,1,RSTART-1) ENVIRON[substr($0,RSTART+1,RLENGTH-2)]
$0 = substr($0,RSTART+RLENGTH)
}
print
}
' file
$ ./tst.sh
Running the build script...
Building finished at 04-14-2020
2005648:7445aa
On: MyLogin
current working directory: /home/MyLogin
but if you really want to do multiple passes calling sed inside a shell loop then ${!variable} is your friend, here's a start:
$ cat tst.sh
#!/bin/env bash
VAR1='2005648'
VAR2='7445aa'
SERVER_NAME='foo'
for var in VAR1 VAR2 SERVER_NAME; do
echo "var, $var, ${!var}"
done
$ ./tst.sh
var, VAR1, 2005648
var, VAR2, 7445aa
var, SERVER_NAME, foo
.
$ VAR1='stuff'
$ var='VAR1'; echo 'foo {VAR1} bar' | sed "s/{$var}/${!var}/"
foo stuff bar
The awk script is robust but YMMV using sed depending on the contents of the variables, e.g. it'd fail if they contain & or / or \1 or .... ENVIRON[] only has access to shell variables set on the awk command line or exported, hence the escape at the end of each line that sets a shell variable so it's part of the awk command line.
You can try this.
#!/usr/bin/env bash
echo "Running the build script..."
VAR1="2005648"
VAR2="7445aa"
SERVER_NAME=$(hostname)
TIMESTAMP=$(date +%m-%d-%Y)
sed "s|{TIMESTAMP}|$TIMESTAMP|;s|{VAR1}|$VAR1|;s|{VAR2}|$VAR2|;s|{SERVER_NAME}|$SERVER_NAME|;s|{PWD}|$PWD|" file.txt
Just add {} in the variables e.g. {$TIMESTAMP} and so on, if you really need it.
That should work unless there is something more that is not included in the question above.

Exporting dependant variable failed in shell script

I have three shell script files, one global variable named "VER" and its value is "2017.4"
1. variable.sh
2. function.sh
3. main.sh
variable.sh
var1=/home
var2=/home/${VER}_version
function.sh
Contain a function named export_function which takes one variable as argument, perform grep operation to find that variable from variable.sh file and export the grep output
export_function () {
var=`grep "$1=" variable.sh | sed -e "s/"$1="//g"`
export $1=$var
}
main.sh
source function.sh
export_function var2
echo "$var2"
When I run the main.sh, get output: /home/${VER}_version instead of /home/2017.4_version
Note: echo $VER in main.sh and function.sh shows value 2017.4
Constrains:
variable.sh is a read-only file
source variable.sh is not allowed
I've rewritten your scripts like that, and it works:
[sahaquiel#sahaquiel-PC ~]$ cat variable.sh
#!/bin/bash
var1=/home
var2="/home/${VAR22}_version"
[sahaquiel#sahaquiel-PC ~]$ cat function.sh
#!/bin/bash
export_function () {
source variable.sh
var=$(echo "var2=${var2}" | grep "$1=" | sed -e "s/"$1="//g")
export $1=$var
}
[sahaquiel#sahaquiel-PC ~]$ cat main.sh
#!/bin/bash
source function.sh
export_function var2
echo "$var2"
[sahaquiel#sahaquiel-PC ~]$ bash main.sh
/home/2017.4_version
[sahaquiel#sahaquiel-PC ~]$ echo $VAR22
2017.4

Parsing text file to variables

$ cat file.txt
example1#domain1-username
I'd like to parse file.txt and export the contents to variables like:
var1=example1#domain1
var2=username
Using just Bash builtins:
$ IFS=- read var1 var2 <<< "$(< file.txt)"
$ declare -p var1 var2
declare -- var1="example1#domain1"
declare -- var2="username"
This sets the field separator IFS to -, then reads the file into the two variables.
<<< "$(< file.txt)" is a but unwieldy, as we're treating the file just like the single line of text that it is.
var1=$(cut -d "-" -f 1 file.txt)
var2=$(cut -d "-" -f 2 file.txt)
The following command will set var1 and var2 in a single pass over file.txt:
. file.txt

Variable $1 as variable

How can I set $1 variable as another variable? I want to run something like:
$ ./script london
Some output with John in text
And the script should be like:
#!/bin/bash
london="John"
ukraina="Yury"
romania="Ion"
cat /path/to/file | grep $1
I don't recommend blindly looking up variable names. A user could pass in any variable, not just one of the three you expect.
Instead, use an associative array.
declare -A names=([london]=John [ukraina]=Yury [romania]=Ion)
grep "${names[$1]}" /path/to/file
Or if your version of bash doesn't support associative arrays, use a case lookup.
case $1 in
london) name=John;;
ukraina) name=Yury;;
romania) name=Ion;;
esac
grep "$name" /path/to/file
#!/bin/bash
london="Jhon"
ukraina="Yury"
romania="Ion"
cat /path/to/file | grep ${!1}
If you want to declare $1 as variable use this:
VARIABLE="$1"
For example:
#!/bin/bash
VARIABLE="$1"
echo $VARIABLE

Cat here document escape all variable but one

I have to write to a file with some bash script. To substitute the variables we can use simply EOF and we escape the substitution with \. But, I want to escape everything, so, I can use 'EOF' and also want to substitute one variable, then how?.
cat > myfile <<'EOF'
$a
$b
$c
$d
$e
$f
$g
.....
.....
$multiple lines like this
EOF
I want to substitute only one variable let $c with it's value. How can I do in this case?. I can't use \ without quoting EOF escaping all the lines as there are many lines.
I just want to escape all the variable substitution('EOF') but want to substitute one variable with its value(How?).
To avoid escaping the many variables but still substitute for one of them, try:
$ cat script
sed 's/$c/3/' >myfile <<'EOF'
$a
$b
$c
$multiple lines like this
EOF
Let's run the script and examine the output file:
$ bash script
$ cat myfile
$a
$b
3
$multiple lines like this
Alternative
This version allows for a variable $c and, thus, may be more flexible:
$ cat script
c=New
sed "s/\$c/$c/" >myfile <<'EOF'
$a
$b
$c
$multiple lines like this
EOF
Execution of this results in:
$ bash script
$ cat myfile
$a
$b
New
$multiple lines like this

Resources