i am newbie on this forum
I am looking for dynamically modifying variable along the code
Ex.
#!/bin/ksh -f
VAR1=123456
VAR2=$VAR1
echo VAR1 # Will return '123456', good
echo VAR2 # Will return '123456', good
VAR1=azerty
echo VAR2 # Will return 123456, not good, I hope it was 'azerty', the new value of VAR1
If anyone has an answer or a hint to this question
Thx in advance,
Antrema
Try nameref, eg:
$ VAR1=123456
$ nameref VAR2=VAR1
$ echo "$VAR1 : $VAR2"
123456 : 123456
$ VAR1=azerty
$ echo "$VAR1 : $VAR2"
azerty : azerty
# NOTE: this relationship works in both directions, eg:
$ VAR2=xyz123
$ echo "$VAR1 : $VAR2"
xyz123 : xyz123
See: O'Reilly: Learning the Korn Shell: 4.4 Indirect Variable References
Related
I am Declaring a variable
var1="D:\TEMP\scripts\test.sh"
echo var1
output:
D:\TEMP\scripts\test.sh
I would like to get the value from var1 and assign to another variable var2 and if I do a echo var2, I should be getting the outting
echo var2
Expected output:
"D:\TEMP\scripts\test.sh"
Sorry ..I got this already. Thought it would be difficult.
[user#server ~]$ var1="D:\TEMP\scripts\test.sh"
[user#server ~]$ echo $var1
D:\TEMP\scripts\test.sh
[user#server ~]$ var2=\"$var1\"
[user#server ~]$ echo $var2
"D:\TEMP\scripts\test.sh"
[user#server ~]$
You'll have to escape the quotes inside the quotes of variable; try this:
var1="\"D:\TEMP\scripts\test.sh\""
var2=$var1
echo $var2
output:
"D:\TEMP\scripts\test.sh"
How can I test if an associative array is declared in Bash? I can test for a variable like:
[ -z $FOO ] && echo nope
but I doesn't seem to work for associative arrays:
$ unset FOO
$ declare -A FOO
$ [ -z $FOO ] && echo nope
nope
$ FOO=([1]=foo)
$ [ -z $FOO ] && echo nope
nope
$ echo ${FOO[#]}
foo
EDIT:
Thank you for your answers, both seem to work so I let the speed decide:
$ cat test1.sh
#!/bin/bash
for i in {1..100000}; do
size=${#array[#]}
[ "$size" -lt 1 ] && :
done
$ time bash test1.sh #best of five
real 0m1.377s
user 0m1.357s
sys 0m0.020s
and the other:
$ cat test2.sh
#!/bin/bash
for i in {1..100000}; do
declare -p FOO >/dev/null 2>&1 && :
done
$ time bash test2.sh #again, the best of five
real 0m2.214s
user 0m1.587s
sys 0m0.617s
EDIT 2:
Let's speed compare Chepner's solution against the previous ones:
#!/bin/bash
for i in {1..100000}; do
[[ -v FOO[#] ]] && :
done
$ time bash test3.sh #again, the best of five
real 0m0.409s
user 0m0.383s
sys 0m0.023s
Well that was fast.
Thanks again, guys.
In bash 4.2 or later, you can use the -v option:
[[ -v FOO[#] ]] && echo "FOO set"
Note that in any version, using
declare -A FOO
doesn't actually create an associative array immediately; it just sets an attribute on the name FOO which allows you to assign to the name as an associative array. The array itself doesn't exist until the first assignment.
You can use declare -p to check if a variable has been declared:
declare -p FOO >/dev/null 2>&1 && echo "exists" || echo "nope"
And to check specifically associative array:
[[ "$(declare -p FOO 2>/dev/null)" == "declare -A"* ]] &&
echo "array exists" || echo "nope"
This is a Community Wiki version of an excellent answer by #user15483624 on a question which is now closed as duplicate. Should that user choose to add their own answer here, this should be deleted in favor of the one with their name on it.
The prior answers on this question should be used only when compatibility with bash 4.x and prior is required. With bash 5.0 and later, an expansion to check variable type is directly available; its use is far more efficient than parsing the output of declare -p, and it avoids some of the unintended side effects of other proposals as well..
The following can be used to test whether a bash variable is an associative array.
[[ ${x#a} = A ]]
${x#a} can be used to test whether it is a variable and an array as well.
$ declare x; echo "${x#a}"
$ declare -a y; echo "${y#a}"
a
$ declare -A z; echo "${z#a}"
A
One of the easiest ways is to the check the size of the array:
size=${#array[#]}
[ "$size" -lt 1 ] && echo "array is empty or undeclared"
You can easily test this on the command line:
$ declare -A ar=( [key1]=val1 [key2]=val2 ); echo "szar: ${#ar[#]}"
szar: 2
This method allow you to test whether the array is declared and empty or undeclared altogether. Both the empty array and undeclared array will return 0 size.
How to set shell variables from an input file ?
hello,
I need to set dynamic variable from an .ini file in a shell script.
Assume the input file is input.ini :
var1=val1
var2=val2
var3=val3
In a script I want to set var1, var & var3 respectively to their val1, val2 & val3 to get
echo $var1
val1
echo $var2
val2
...
I've tryed :
file="input.ini"
while IFS== read -r f1 f2
do
eval dynvar=$f1
dynvar=$f2
done <"$file"
echo $var1
echo $var2
echo $var3
the echo $varx commands give no output. How can I work it out ?
thanks in advance.
source input.ini
Or
. input.ini
More info
<source | .> filename [arguments]
Execute commands from a file in the current shell.
Solved
using :
file="install.ini"
while IFS== read -r f v
do
eval "$f=$v"
done <"$file"
did the trick.
Is there a way to do the default values ${foo:-bar} and the remove matching suffix ${foo%bar} bash feature in the same time ?
Something like that: ${foo%suffix:-default}
In other words, I want:
If foo is unset or null use the default value
If foo is set remove any suffix at the end
Something like that: ${foo%suffix:-default}
It's not possible to achieve what you want in a manner similar to what you've described.
However, you could use control operators to achieve the desired result without making use of temporary variables:
$ FOO=foobar
$ [ -z "$FOO" ] && FOO=default || FOO=${FOO%bar}
$ echo $FOO
foo
$ FOO=
$ [ -z "$FOO" ] && FOO=default || FOO=${FOO%bar}
$ echo $FOO
default
You could use default assignment instead of default substitution. This is also a use for the : "no-op" command:
: ${foo:=default}
echo ${foo%suffix}
testing:
$ default=foobar suffix=bar
$ foo=hello ; : ${foo:=$default}; echo $foo ${foo%$suffix}
hello hello
$ foo=ironbar; : ${foo:=$default}; echo $foo ${foo%$suffix}
ironbar iron
$ unset foo ; : ${foo:=$default}; echo $foo ${foo%$suffix}
foobar foo
I explained my question in the comments:
VAR=
INS="Installing $VAR"
echo $INS
. # In each echo command I want to dynamically substitute
. # the $VAR variable in the $INS variable. I want to do
echo $INS # the substitution of the variable on echo command.
Is this possible?
You need a function to do the job gracefully.
say() {
echo "Installing $INS"
}
INS=hello
say
INS=world
say
Or just this:
say() {
echo "Installing $#"
}
say hello
say world
For example:
[ghoti#pc ~]$ cat varins
#!/bin/bash
msg='Installing "$VAR"'
for VAR in foo bar baz; do
eval echo "$msg"
done
[ghoti#pc ~]$ ./varins
Installing foo
Installing bar
Installing baz
[ghoti#pc ~]$
This relies on the fact that $VAR won't be expanded inside single quotes. The eval command will expand the $msg variable, in which the shell will find $VAR to replace.
Parameter substitution can do it also:
ins='aaa $var aaa'
var='xxx'
echo "'${ins//\$var/$var}'"
result:
'aaa xxx aaa'
INS='Installing $VAR'
result=`eval "echo $INS"`
echo $result
you have to use single quotes to not substitute $VAR on creation of INS
eval evaluates $INS at runtime and with echo and backticks it is returned as substituted string
As Hachi said, you need single quotes to prevent $VAR from premature evaluation. Graham suggests in the comments to avoid the subshell call like this:
#!/bin/bash
VAR=17
INS='Installing $VAR'
eval "echo \"$INS\""
VAR=42
eval "echo \"$INS\""
If you don't do it:
VAR=23
INS="Installing $VAR"
echo $(eval "echo $INS")
VAR=8
echo $(eval "echo $INS")
23 is bound immediately, and the assignment VAR=8 isn't noticed.
Result:
Installing 17
Installing 42
Installing 23
Installing 23