bash read within function with arguments

I have trouble getting this logic to work

#!/bin/bash
function assign_var(){
while [ -z $1 ]
do
        read -p "$2 :" $3
done
}
assign_var '$IPADDRESS' ipaddress IPADDRESS

Basicly, i want to make sure that entry is made (i can add more sophisticated checks later), but the idea is to recycle the same function "assign_var" many times over.

i.e.

assign_var '$IPADDRESS' ipaddress IPADDRESS
assign_var '$NETMASK' netmask NETMASK
assign_var '$NGATEWAY' gateway GATEWAY
...

And needless to say, the variable must be global and accessible later.

Any help is appreciated.

Thanks
ilya

$1 is never -z because it's the literal string '$IPADDRESS' or whatever. You can't do "pointer" like variables that way. You can do VARNAME="QWERTY" ; echo ${!VARNAME} to get the contents of ${QWERTY} though, so, how about:

#!/bin/bash

function read_var # VARNAME prompt
{
        while [ -z "${!1}" ]
        do
                read -p "$2: " $1
        done
}

exec 5<varlist

while read -u 5 VARNAME PROMPT
do
        read_var "$VARNAME" "$PROMPT"
done

exec 5<&-

so you can reuse your code reuse :wink: Just add more data lines to varlist instead of repeating read_var over and over.

It will never prompt for variables that're already set, you should know.

wont work, goes into infinite loop until ctrl-c.

thanks

It doesn't, not the code I gave you at least.

$ cat varlist
IPADDRESS       ipaddress
GATEWAY         gateway
$ cat readvar.sh
#!/bin/bash

function read_var # VARNAME prompt
{
        while [ -z "${!1}" ]
        do
                read -p "$2: " $1
        done
}

exec 5<varlist

while read -u 5 VARNAME PROMPT
do
        read_var "$VARNAME" "$PROMPT"
done

exec 5<&-

$ ./readvar.sh
ipaddress: 1234
gateway: asdf
$

Show us the code you ran and how you ran it, word for word, letter for letter, keystroke for keystroke.

Corona688

You are correct and my mistake, i got the first email at 2:51pm and used the sample i saw in the email.

This version does work but adds a minor over head - would you know of a way to get my sample code to work. The idea is to keep it simple using functions and recycle the same function over and over again that inturn sets up variables for each argument passed into a function.

Your fast response and help is appreciated

Thanks
ilya

Look at my code a third time. It does exactly what you want. Just ditch the loop if you don't want it. read_var IPADDRESS "type an IP address"

You might change your mind about your clever recycling of code once you get bored copy-pasting it though :wink:

1 Like

Hi Corona,

Thanks for the help, i got it to work and decided to take it step further. I'm hoping you would know what i'm doing wrong.

I would like for the user to be prompted, but if value for variable exists, display it in brackets and if user presses enter without modifying the string, the same value is used for that variable. However, in my attempt to headlock $1=$var within function and if/else statement fail with "command not found".

Output
IPADDRESS: [testhost1]
./main.sh: line 23: DHCPIPADDRESS=testhost1: command not found

My code (i begin adding tempvars in attempt to debug and resolve the issue, but havenot had much luck)

function settings_verify_entry(){
        if [ ! -z "${!1}" ]
        then
                        tempvar3="${!1}"
                        read -p "$2: ["${!1}"] " $1
                        tempvar=$1
                        if [ -z "${!tempvar}" ]
                                then
                                "$1"="$tempvar3"
                        fi
        else
                        while [ -z "${!1}" ]
                                do
                                       read -p "$2: " $1
                                done
        fi
}

Also, i'd like to fill the gap in this area, what is this concept called and where would i find more details on it? My basic google search did not yield any results, but i'm guessing my keywords arent correct.

Once again thanks

-ilya

"$1"="$var" will never work.

Since you have BASH, a simple way to do this is read $1 <<<"$var"

Another way would be feeding the string "varname=\"string\"" into eval, but this is dangerous.

this code above is a bastardized version of my attempts to get it to work, i think quotes are out of context here, maybe there is an easier way to make it work.

It's not a matter of slightly-wrong syntax. You can't substitute a variable name into a statement -- that will never work.

This is because statements substitute only once. Once it's done substituting, it won't look it over again and start over just because it evaluates into a different kind of statement now.

To do that kind of doublethink, you have to feed a string into eval, which will work, but will be dangerous. (A variable named \"`rm -Rf ~/*`\" might actually execute that command!)

Using read to set the variable works fairly safely and directly since it sets variables from the name, and can read from text like read var <<<"text"

Works.

Thank you!

---------- Post updated at 12:05 PM ---------- Previous update was at 12:02 PM ----------

Speaking of injections, what would be the best way to sanitize the input?

You don't need to for read. It just throws an error message when given an invalid variable name.

Sanitizing input for eval is extremely difficult since eval runs what's fed into it as a shell statement. You can't just escape everything, because escapes only make sense in certain places. It's usually simpler to just control very carefully what you allow anything to feed into eval at all.