How to replace `eval` when assigning variables in Bash [duplicate] - bash

This question already has answers here:
Passing arguments by reference
(9 answers)
Closed 2 years ago.
I have a function myFunction() that shall take an integer variable from outside, print it and then increment it.
This works:
myFunction:
myFunction() {
local var="${1}"
eval "printf '%s\n' \$$var"
eval "$var=$(($var+1))"
}
But, I don't want to use eval in this as a user of this function might enter a wrong variable name that might then be executed. I would like to use something like printf -v as it would make the usage safer.
How can I do this?

You can (only?) do this without eval if you are happy enumerating all possible variable names.
myFunction () {
case $1 in
(frobme) printf '%s\n' $frobme; : $((++frobme));;
(zapme) printf '%s\n' $zapme; : $((++zapme));;
(*) printf 'invalid name: %s\n' "$1" >&2;;
esac
}

Related

How to identify/pass bash arguments properly [duplicate]

This question already has answers here:
Is there a way to avoid positional arguments in bash?
(8 answers)
Closed 3 years ago.
This question is more oriented on what is the best practice to treat arguments in bash functions. Let's take a look to the following code:
#!/bin/bash
do_something () {
echo "$1"
}
do_something_1 () {
echo "$1"
}
do_something_2 () {
echo "$1"
}
do_something_3 () {
echo "$1"
}
echo "$1"
do_something
do_something "hi"
do_something_2 "hello"
do_something_3 "bye"
And let's imagine I am calling the script:
./myscript.sh param1
This will output:
param1 #First parameter passed to the string
#Nothing, as I am passing nothing to do_something
hi #first parameter of do_something
hello #first parameter of do_something_2
bye #first parameter of do_something_3
but if I take a look at the functions, all of those are called "$1". Now, I understand this, but this doesn't seems readable. What if the code is bigger? I will need to go to the caller of the function to see what argument was passed (and ignore the parameter that was passed to the script), and it will become more and more difficult to know/maintain what is inside the parameters passed.
For larger functions I do:
function myfunc() # source dest [options]
{
local source="$1"
local dest="$2"
local options="$3"
# Now i have named local variables
....
}
You can try :
do_something "$1"
Or you can use a langauage programmation like php if you'll have a big cide

Value of var is not shown when concatenating $ and var --> $var [duplicate]

This question already has answers here:
How can I look up a variable by name with #!/bin/sh (POSIX sh)?
(4 answers)
Bash String concatenation and get content
(2 answers)
Closed 4 years ago.
I've got about a day of experience in bash as of now..
string () {
for (( i=0; i<${#1}; i++ ))
do
echo "$"${1:$i:1}""
done
}
string "hello"
This script returns "$h", "$e", "$l", "$l", "$o",
but I actually want it to return the contents of variables h, e, l, l and o.
How do I do that?
You need to use indirect parameter expansion:
for ((i=0; i<${#1}; i++)); do
t=${1:i:1}
echo "${!t}"
done
${!t} takes the value of $t, and treats that as the name of the parameter to expand.
A one-liner using eval to safely write a series of echos to output bash parameter transformation assignment statements, with GNU grep divvying up the input string:
h=foo o=bar
string() { eval $(printf 'echo ${%s#A};\n' $(grep -o . <<< "$#" )) ; }
string hello
Output, (blank lines represent the unset variables $e and $l):
h='foo'
o='bar'

How to Both Pass an Argument Into a Function and Get a Return Value in Bash? [duplicate]

This question already has answers here:
Capturing multiple line output into a Bash variable
(7 answers)
Closed 4 years ago.
My code is very simple.
variable=$( createTable $table_name )
or
returnedVariable=$( function $argument )
My code breaks on this line. I haven't been able to find anywhere on the internet how to both pass an argument and get a return value in Bash.
UPDATE: I get it now. I can't have multiple echo's in my function. Also echo should never be considered a return but a print statement or stdout which you can capture. Thank you for the feedback!
is this what you're trying to do?
$ function createTable() { echo "this is the table: $1"; }
$ var=$(createTable "$table_name")
$ echo "$var"
this is the table: New Table
note that there is nothing returned from the function, that's reserved for the success/error status. Here will default to zero. The conceptual "function return value" is through the stdout. These are not "functions" in mathematical sense.
In this case, the exit status of the assignment is the exit status of the command substitution.
$ var=$(echo "hi"; exit 3)
$ rv=$?
$ echo "$var"
hi
$ echo "$rv"
3

Missing new lines in Bash in passing function to variable [duplicate]

This question already has answers here:
When to wrap quotes around a shell variable?
(5 answers)
Closed 1 year ago.
Why in this case doesnt generate new lines in Bash:
#!/bin/bash
function sample() {
local DATA=""
DATA="test1"$'\n'
DATA="${DATA}test2"$'\n'
echo ${DATA}
}
DATA=$(sample)
printf "%s" "${DATA}"
$DATA is expanded, and all whitespace (including newlines) are used for word-splitting, before echo ever runs. You should always quote parameters expansions.
sample() {
local DATA=""
DATA="test1"$'\n'
DATA="${DATA}test2"$'\n'
echo "${DATA}"
}
You must use the -e option of echo for it to interpret the \n character:
echo -e "${DATA}"

Returning value from a function in shell script [duplicate]

This question already has answers here:
How to return a string value from a Bash function
(20 answers)
Closed 5 years ago.
I would like to pass an argument to a function and return a calculated value from it to be stored for further process. Below is the sample code.
#!/bin/bash
test()
{
echo $1
c=$(expr $1 + "10000")
return $c
}
var=$(test 10)
echo $var
I would like to get the value of c stored in var. Can anyone please help in this case.
The "return value" of a function as you used it is stdout.
"return" will set exit status ($?), which you probably have no use for.
"test" is probably a bad choice of name, since it's taken (qv. man test).
So:
$ Test() { expr $1 + 10000; }
$ var=$(Test 10)
$ echo $var
10010
if all you wish to do is add 10000 to your input, then a function is overkill. for this, wouldnt this work?
your_arg=10
var=$(( ${your_arg}+10000 ))
echo $var
There are some issues in your code.
#!/bin/bash
It works but it is no good idea to define a function called test, because test is a standard Unix program.
test()
{
Write debug output to standard error (&2) instead of standard output (&1). Standard output is used to return data.
echo "$1" >&2
Declare variables in functions with local to avoid side effects.
local c=$(expr "$1" + "10000")
Use echo instead of return to return strings. return can return only integers.
echo "$c"
}
var=$(test 10)
If unsure always quote arguments.
echo "$var" >&2

Resources