I want to create env parameter
that the key is a:b or a#b
I need to do it from bash script or from terminal , it should work from linux or windows
when I tried it export a:b=c
I got an error
not a valid identifier
When I tried
export tempKey = a:b then It worked but then I didn't know how to use the value a:b to create it as key
Could you please advise ?
None of the commonly used unix shells will let you create a var whose name includes characters not legal in an identifier (typically letters, digits and underscore). The simplest workaround is to use the env command since it doesn't impose any restrictions on the strings it puts in the environment. For example, env a:b=c a_cmd where a_cmd is whatever command needs that environment string. If you want it to be part of the shell's environment do exec env a:b=c $SHELL. Obviously the new shell won't be able to use that var since $a:b is not a valid var reference even if you enclose the var name in braces.
Related
I'm having 2 Variables inside a variable group and their values are as shown below:
cr 2200
tr cd1200
I would like to assign these two variables to a third variable cd as shown below:
cd '2200;cd1200;abc.txt'
I'm trying to use below script but it is showing too many arguments.
Can someone please help in this.
I'm using below code:
cd = \'"$cr";"$tr";abc.txt\'
echo "$cd"
I need output as:
cd = '2200;cd1200;abc.txt'
Using Azure macro syntax ($(<varName>)):
$cd = '$(cr);$(tr);abc.txt'
Note:
PowerShell always needs the $ sigil when accessing a variable - even when assigning to it (unlike in POSIX-compatible shells such as Bash).
Azure's macro syntax - which textually expands references to Azure variables up front, before PowerShell sees the code, is not be confused with PowerShell's subexpression operator ($(...))
I'm trying to obtain a secret out of my KeyVault.
The variable name is secretVar.
Obtaining the secret like this: $(secretVar) works fine however I would like to retrieve it from a variable like this:
I keep getting command not found and I've no idea why this shouldn't be working.
So the name of the secret I want to extract is inside a bash variable. For this question I've simplified the problem but in my real use case I have a bash for loop which loops through secret names and inside the for loop I want to extract the appropriate value from the KeyVault with the corresponding secret name like this:
for secretname in secrets; do
echo $($secretname) # This should contain the value of the secret but gives command not found
done
If anyone has an idea what could be happening, any help is very appreciated.
Thanks in Advance!
Look at the syntax you're using.
variable=secretVar
You are creating an environment variable with the literal value secretVar
Then you try to execute the value of the variable $variable with $($variable). So it tries to run the command secretVar, which obviously doesn't exist, and you get an error message.
The syntax you're looking for is
variable=$(secretVar)
just like you used in the first echo command in the script.
If you don't want to run the variable value as a command, the syntax would be $variable, not $($variable)
$variable is the syntax for a Bash environment variable.
$(variable) is the syntax for referencing Azure DevOps variables.
First of all, the script keyword is a shortcut for the command-line task. The task runs a script using cmd.exe on Windows and Bash on other platforms. You need to pay attention to the agent you are using.
If you want to set variables in scripts, you can use task.setvariable logging command. For example:
- script: |
echo $(secretvar)
echo "##vso[task.setvariable variable=variable]$(secretvar)"
- script: |
echo $(variable)
You can find more detailed information in this document.
How can I retrieve a bash variable value if I have the variable name as string? var1="this is the real value"
a="var1"
Do something to get value of var1 just using variable a.
Context:
I have some AMI's (Amazon Machine Image) and I want to fire up a few instances of each AMI. As soon as they finish booting, I want to setup each instance according to its AMI type. I don't want to bake lots of scripts or secret keys inside any AMI so I prepared a generalized startup script and I put it on S3 with a publicly accessible link. In rc.local I put small piece of code which fetches the startup script and executes it. This is all I have in the AMIs. Then each AMI accesses a common configuration script which is applicable to all AMIs and special setup scripts for each. These scripts are private and require a signed URL to access them.
So now, when I fire an instance of an AMI (my_private_ami_1), I pass a signed URL for one more file presented on S3 which contains signed URL for all private scripts in terms of key/value pair.config_url="http://s3.amazo.../config?signature"
my_private_ami_1="http://s3.amazo.../ami_1?signature"
...
When the startup script runs, it downloads the above file and source's it. Then it checks for its AMI type and picks the correct setup script for itself.
ami\_type=GET AMI TYPE #ex: sets ami\_type to my\_private\_ami\_1
setup\_url=GET THE SETUP FILE URL BASED ON AMI\_TYPE # this is where this problem arises
So now I can have a generic code which can fire instances irrespective of their AMI types and instances can take care of themselves.
You can use ${!a}:
var1="this is the real value"
a="var1"
echo "${!a}" # outputs 'this is the real value'
This is an example of indirect parameter expansion:
The basic form of parameter expansion is ${parameter}. The value of
parameter is substituted.
If the first character of parameter is an exclamation point (!), it
introduces a level of variable indirection. Bash uses the value of the
variable formed from the rest of parameter as the name of the
variable; this variable is then expanded and that value is used in the
rest of the substitution, rather than the value of parameter itself.
X=foo
Y=X
eval "Z=\$$Y"
sets Z to foo.
For my fellow zsh users, the way to accomplish the same thing as the accepted answer is to use:
echo ${(P)a} # outputs 'this is the real value'
It is appropriately called Parameter name replacement
This forces the value of the parameter name to be interpreted as a
further parameter name, whose value will be used where appropriate.
Note that flags set with one of the typeset family of commands (in
particular case transformations) are not applied to the value of name
used in this fashion.
If used with a nested parameter or command substitution, the result of
that will be taken as a parameter name in the same way. For example,
if you have ‘foo=bar’ and ‘bar=baz’, the strings ${(P)foo},
${(P)${foo}}, and ${(P)$(echo bar)} will be expanded to ‘baz’.
Likewise, if the reference is itself nested, the expression with the
flag is treated as if it were directly replaced by the parameter name.
It is an error if this nested substitution produces an array with more
than one word. For example, if ‘name=assoc’ where the parameter assoc
is an associative array, then ‘${${(P)name}[elt]}’ refers to the
element of the associative subscripted ‘elt’.
Modified my search keywords and Got it :). eval a=\$$a Thanks for your time.
In bash 4.3+, you can use declare -n:
#!/usr/bin/env bash
var="this is the real value"
var_name="var"
declare -n var_ref=$var_name
echo "${var_ref}"
Had the same issue with arrays, here is how to do it if you're manipulating arrays too :
array_name="ARRAY_NAME"
ARRAY_NAME=("Val0" "Val1" "Val2")
ARRAY=$array_name[#]
echo "ARRAY=${ARRAY}"
ARRAY=("${!ARRAY}")
echo "ARRAY=${ARRAY[#]}"
echo "ARRAY[0]=${ARRAY[0]}"
echo "ARRAY[1]=${ARRAY[1]}"
echo "ARRAY[2]=${ARRAY[2]}"
This will output :
ARRAY=ARRAY_NAME[#]
ARRAY=Val0 Val1 Val2
ARRAY[0]=Val0
ARRAY[1]=Val1
ARRAY[2]=Val2
In bash 4.3, the '-v' test for set variables was introduced. At the same time, 'nameref' declaration was added. These two features together with the indirection operator (!) enable a simplified version of the previous example:
get_value()
{
declare -n var_name=$1
if [[ -v var_name ]]
then
echo "${var_name}"
else
echo "variable with name <${!var_name}> is not set"
fi
}
test=123
get_value test
123
test="\$(echo \"something nasty\")"
get_value test
$(echo "something nasty")
unset test
get_value test
variable with name <test> is not set
As this approach eliminates the need for 'eval', it is safer.
This code checked under bash 5.0.3(1).
modern shells already support arrays( and even associative arrays). So please do use them, and use less of eval.
var1="this is the real value"
array=("$var1")
# or array[0]="$var1"
then when you want to call it , echo ${array[0]}
Based on the answer: https://unix.stackexchange.com/a/111627
###############################################################################
# Summary: Returns the value of a variable given it's name as a string.
# Required Positional Argument:
# variable_name - The name of the variable to return the value of
# Returns: The value if variable exists; otherwise, empty string ("").
###############################################################################
get_value_of()
{
variable_name=$1
variable_value=""
if set | grep -q "^$variable_name="; then
eval variable_value="\$$variable_name"
fi
echo "$variable_value"
}
test=123
get_value_of test
# 123
test="\$(echo \"something nasty\")"
get_value_of test
# $(echo "something nasty")
VALUE=$(eval "echo \$$SOME_VAR_NAME")
Example
SSH_KEY_FILE_PATH_FOO="/tmp/key"
SSH_KEY_FILE_PATH_VAR_NAME_PREFIX="SSH_KEY_FILE_PATH"
SSH_KEY_FILE_PATH_VAR_NAME_SUFFIX="FOO"
SSH_KEY_FILE_PATH=$(eval "echo \$${SSH_KEY_FILE_PATH_VAR_NAME_PREFIX}_${SSH_KEY_FILE_PATH_VAR_NAME_SUFFIX}")
echo "$SSH_KEY_FILE_PATH"
/tmp/key
I am writing a Perl script that is run by a user and makes use of the current Linux environment as variables and other variables as well. The environment settings may change and be different from what they were originally.
However, I'm trying to use self-contained Perl Modules and need to be able to access these variables. What is the best practice to go about doing this? I can just pass along 10 variables when I create an object using the Perl Module, but that seems excessive...
Thanks
The environment variables are accessible from anywhere in the global %ENV hash:
print $ENV{HOME};
If you are creating objects, they probably have some attributes (being the objects hashes, arrays or even inside out objects...) Just store the relevant values into the attributes, e.g.
my $obj = Some::Package->new( name => 'Homer',
surname => 'Simpson',
city => 'Springfield',
# ... 7 more
);
How can I retrieve a bash variable value if I have the variable name as string? var1="this is the real value"
a="var1"
Do something to get value of var1 just using variable a.
Context:
I have some AMI's (Amazon Machine Image) and I want to fire up a few instances of each AMI. As soon as they finish booting, I want to setup each instance according to its AMI type. I don't want to bake lots of scripts or secret keys inside any AMI so I prepared a generalized startup script and I put it on S3 with a publicly accessible link. In rc.local I put small piece of code which fetches the startup script and executes it. This is all I have in the AMIs. Then each AMI accesses a common configuration script which is applicable to all AMIs and special setup scripts for each. These scripts are private and require a signed URL to access them.
So now, when I fire an instance of an AMI (my_private_ami_1), I pass a signed URL for one more file presented on S3 which contains signed URL for all private scripts in terms of key/value pair.config_url="http://s3.amazo.../config?signature"
my_private_ami_1="http://s3.amazo.../ami_1?signature"
...
When the startup script runs, it downloads the above file and source's it. Then it checks for its AMI type and picks the correct setup script for itself.
ami\_type=GET AMI TYPE #ex: sets ami\_type to my\_private\_ami\_1
setup\_url=GET THE SETUP FILE URL BASED ON AMI\_TYPE # this is where this problem arises
So now I can have a generic code which can fire instances irrespective of their AMI types and instances can take care of themselves.
You can use ${!a}:
var1="this is the real value"
a="var1"
echo "${!a}" # outputs 'this is the real value'
This is an example of indirect parameter expansion:
The basic form of parameter expansion is ${parameter}. The value of
parameter is substituted.
If the first character of parameter is an exclamation point (!), it
introduces a level of variable indirection. Bash uses the value of the
variable formed from the rest of parameter as the name of the
variable; this variable is then expanded and that value is used in the
rest of the substitution, rather than the value of parameter itself.
X=foo
Y=X
eval "Z=\$$Y"
sets Z to foo.
For my fellow zsh users, the way to accomplish the same thing as the accepted answer is to use:
echo ${(P)a} # outputs 'this is the real value'
It is appropriately called Parameter name replacement
This forces the value of the parameter name to be interpreted as a
further parameter name, whose value will be used where appropriate.
Note that flags set with one of the typeset family of commands (in
particular case transformations) are not applied to the value of name
used in this fashion.
If used with a nested parameter or command substitution, the result of
that will be taken as a parameter name in the same way. For example,
if you have ‘foo=bar’ and ‘bar=baz’, the strings ${(P)foo},
${(P)${foo}}, and ${(P)$(echo bar)} will be expanded to ‘baz’.
Likewise, if the reference is itself nested, the expression with the
flag is treated as if it were directly replaced by the parameter name.
It is an error if this nested substitution produces an array with more
than one word. For example, if ‘name=assoc’ where the parameter assoc
is an associative array, then ‘${${(P)name}[elt]}’ refers to the
element of the associative subscripted ‘elt’.
Modified my search keywords and Got it :). eval a=\$$a Thanks for your time.
In bash 4.3+, you can use declare -n:
#!/usr/bin/env bash
var="this is the real value"
var_name="var"
declare -n var_ref=$var_name
echo "${var_ref}"
Had the same issue with arrays, here is how to do it if you're manipulating arrays too :
array_name="ARRAY_NAME"
ARRAY_NAME=("Val0" "Val1" "Val2")
ARRAY=$array_name[#]
echo "ARRAY=${ARRAY}"
ARRAY=("${!ARRAY}")
echo "ARRAY=${ARRAY[#]}"
echo "ARRAY[0]=${ARRAY[0]}"
echo "ARRAY[1]=${ARRAY[1]}"
echo "ARRAY[2]=${ARRAY[2]}"
This will output :
ARRAY=ARRAY_NAME[#]
ARRAY=Val0 Val1 Val2
ARRAY[0]=Val0
ARRAY[1]=Val1
ARRAY[2]=Val2
In bash 4.3, the '-v' test for set variables was introduced. At the same time, 'nameref' declaration was added. These two features together with the indirection operator (!) enable a simplified version of the previous example:
get_value()
{
declare -n var_name=$1
if [[ -v var_name ]]
then
echo "${var_name}"
else
echo "variable with name <${!var_name}> is not set"
fi
}
test=123
get_value test
123
test="\$(echo \"something nasty\")"
get_value test
$(echo "something nasty")
unset test
get_value test
variable with name <test> is not set
As this approach eliminates the need for 'eval', it is safer.
This code checked under bash 5.0.3(1).
modern shells already support arrays( and even associative arrays). So please do use them, and use less of eval.
var1="this is the real value"
array=("$var1")
# or array[0]="$var1"
then when you want to call it , echo ${array[0]}
Based on the answer: https://unix.stackexchange.com/a/111627
###############################################################################
# Summary: Returns the value of a variable given it's name as a string.
# Required Positional Argument:
# variable_name - The name of the variable to return the value of
# Returns: The value if variable exists; otherwise, empty string ("").
###############################################################################
get_value_of()
{
variable_name=$1
variable_value=""
if set | grep -q "^$variable_name="; then
eval variable_value="\$$variable_name"
fi
echo "$variable_value"
}
test=123
get_value_of test
# 123
test="\$(echo \"something nasty\")"
get_value_of test
# $(echo "something nasty")
VALUE=$(eval "echo \$$SOME_VAR_NAME")
Example
SSH_KEY_FILE_PATH_FOO="/tmp/key"
SSH_KEY_FILE_PATH_VAR_NAME_PREFIX="SSH_KEY_FILE_PATH"
SSH_KEY_FILE_PATH_VAR_NAME_SUFFIX="FOO"
SSH_KEY_FILE_PATH=$(eval "echo \$${SSH_KEY_FILE_PATH_VAR_NAME_PREFIX}_${SSH_KEY_FILE_PATH_VAR_NAME_SUFFIX}")
echo "$SSH_KEY_FILE_PATH"
/tmp/key