I have a TARGET variable that can be set to dev, test or prod.
I defined the following lists:
dev=(server1 user1 target1)
test=(server2 user2 target2)
prod=(server3 user3 target3)
Depending on the value of TARGET, I'd like to dynamically associate the variable CONFIG to one of the list.
Let's say TARGET=dev. I then have
eval CONFIG=\$$TARGET # I expect CONFIG to be a list containing (server1 user1 target1)
echo ${CONFIG[*]} # OK, it gives (server1 user1 target1)
echo ${CONFIG[1]} # I would expect to have "server1" but it returns "1", seems like CONFIG is not seen as a list
Any idea ?
eval CONFIG=\$$TARGET sets CONFIG to the string $TARGET. When an array is expanded in a string context, the result is the concatenation of the values in the array, with the first character of IFS inserted as a separator. Thus after the assignment the value of CONFIG is the string server1 user1 target1.
You need to assign to CONFIG as an array. Since you're working in zsh, you don't need to use eval to obtain the value of a variable whose name is in a variable. Use the P parameter expansion flag.
CONFIG=(${(P)TARGET})
Related
I have a dictionary that has variable names in the value string.
I'm trying to lookup the dictionary value, then parse the result with the actual variable value in the string (not the variable name).
How would I do it?
Example:
asset_symbol='BTC'
counter_asset_symbol='ETH'
Dictionary entry:
['ct']=https://charts.cointrader.pro/charts.html?coin=$asset_symbol%3A$counter_asset_symbol
When calling the value I want it to parse $asset_symbol and $counter_asset_symbol" to "BTC" and "ETH"
So in this case I want:
https://charts.cointrader.pro/charts.html?coin=BTC%3AETH
Examples of what didn't work:
#!/bin/bash
chart_engines=('ct cg')
# No ''
declare -A search_urls=(
['ct']=https://charts.cointrader.pro/charts.html?coin=$asset_symbol%3A$counter_asset_symbol
['cg']=https://beta.coinigy.com/markets/$exchange_symbol/$asset_symbol/$counter_asset_symbol
)
# With single quotes
declare -A search_urls=(
['ct']='https://charts.cointrader.pro/charts.html?coin=$asset_symbol%3A$counter_asset_symbol'
['cg']='https://beta.coinigy.com/markets/$exchange_symbol/$asset_symbol/$counter_asset_symbol'
)
# With double quotes
declare -A search_urls=(
['ct']='https://charts.cointrader.pro/charts.html?coin=$asset_symbol%3A$counter_asset_symbol'
['cg']='https://beta.coinigy.com/markets/$exchange_symbol/$asset_symbol/$counter_asset_symbol'
)
asset_name='Bitcoin'
asset_symbol='BTC'
counter_asset_name='Ethereum'
counter_asset_symbol='ETH'
exchange_name='Binance'
exchange_symbol="BINA"
open_charts_urls(){
for i in ${chart_engines[#]}; do
# Get URL
# Dictonary lookup doesn't fill in the variables.
local charts_url="${search_urls[$i]}"
echo "$charts_url"
# Direct reference does.
# echo "https://beta.coinigy.com/markets/$exchange_symbol/$asset_symbol/$counter_asset_symbol"
# echo "https://charts.cointrader.pro/charts.html?coin=$asset_symbol%3A$counter_asset_symbol"
# local subs="$charts_url"
# echo "subs:$subs"
done
}
open_charts_urls
You are referencing $asset_symbol and $counter_asset_symbol before they are declared. Declare the $search_urls array below the declaration of these symbols. Also, use double quotes for the values within the array. Single quotes will prevent the parameter substitution. See quoting. In your example below the comment # With double quotes you are still using single quotes.
I have a shell script that sets a variable RESULT= as empty to begin with. Then, the script makes a curl get request if RESULT is empty (if [ -z $RESULT ];then...), and then prints it out, telling the user to set the empty variable.
I am wondering if there is a way for me to in-line modify the RESULT variable only if it is empty, so that afterwards, the variable instead reads a string, such as
RESULT="SUCCESS"
Simply use
: ${RESULT:=$(curl ...)
If RESULT is initially empty or unset, curl will run and its output assigned to RESULT. Otherwise, curl is not run, and RESULT retains whatever value it started with. (Note that RESULT may be an environment variable, with a value before the script actually starts.)
You can extend this to handle arguments as well.
# :-, not :=
RESULT=${1:-$(curl ...)}
curl only runs if the first argument is the empty string or not present:
yourScript
yourScript ""
Otherwise, it assigns whatever the first argument is to RESULT:
yourScript "$(curl ...)"
Supply an assigning default.
if [[ b0Gus == "${RESULT:=b0Gus}" ]]; then... # RESULT now b0Gus if it was empty
This returns the value of RESULT if it has one, else it sets it and returns that. Note that it is more like ((++x)) than ((x++)) in that it applies the change before returning the content to the test operator.
If you use a dash instead of equals, it returns the alternate value, but doesn't set the variable -
if [[ b0Gus == "${RESULT:-b0Gus}" ]]; then... # RESULT still empty after match
See https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html for more.
You can apply this by passing it as args to a no-op, too.
: ${RESULT:=b0Gus}
The : just returns true, but the parser still evaluates its arguments, which will set the var if empty - this is similar to a Perl ||= assignment, though that isn't inline.
In Bash, I am trying to create a path with two variables within:
/path/to/my/file/${variable1_-}${variable2}/Still/some/path
My variable2 is always set, but the variable1 might be empty and in that case I don't want to print the "_"
I have tried the line above, but doesn't seem to be correct.
Can someone help in getting the right path printed?
Thanks in advance for your suggestions!
You have a simple typo (the underscore should be after the separator, not part of the variable name) and you want to include the underscore if variable1 is set, not it it's unset (so plus instead of minus in the parameter expansion; and add a colon to also cover the set but empty case). Presumably you also want to include the actual value of variable1 when it's set.
/path/to/my/file/${variable1}${variable1:+_}${variable2}/Still/some/path
or equivalently, nested
/path/to/my/file/${variable1:+${variable1}_}${variable2}/Still/some/path
where the braces before the underscore are necessary to separate the variable name from the literal text.
You can use this.
https://linux.die.net/man/1/bash
${parameter:+word}
set also variable1
variable1=VAR1
variable2=VAR2
variable3=${variable1:+_}
echo /path/to/my/file/${variable1}${variable3}${variable2}/Still/some/path
set only variable2
variable1=
variable2=VAR2
variable3=${variable1:+_}
echo /path/to/my/file/${variable1}${variable3}${variable2}/Still/some/path
With a few more lines of code this could work:
run () {
prefix="" # empty
if [ -n "$variable1" ]; then
prefix="${variable1}_"
fi
echo "/path/to/my/file/${prefix}${variable2}/Still/some/path"
}
# set only variable2
variable2=var2
run
# set also variable1
variable1=var1
run
output:
/path/to/my/file/var2/Still/some/path
/path/to/my/file/var1_var2/Still/some/path
description:
-n tests if the string is not empty, in that case I fill prefix with variable1 and the underscore
I'm unable to substitute the argument value(s) in the bash command as below:
# echo $int1
{"id":"74953939-fd20-4472-8aaa-067e6f4c4106"}
# echo $int2
{"id":"5ef4664d-3600-4df9-a6a9-01ffb0f49422"}
# echo $int3
{"id":"6dc95c01-742e-4225-8298-e5750fe67f27"}
# set -x
# data set net-agent interfaces '["$int1", "$int2", "$int3"]'
+ data set net-agent interfaces '["$int1", "$int2", "$int3"]'
Any idea on why the values are not being substituted?
Thanks!
I'm guessing that the argument to the command should be valid JSON, in which case you should remove the double quotes from around each variable and wrap the entire string in double quotes so variables are expanded:
data set net-agent interfaces "[$int1, $int2, $int3]"
Using set -x, this produces:
$ data set net-agent interfaces "[$int1, $int2, $int3]"
+ data set net-agent interfaces '[{"id":"74953939-fd20-4472-8aaa-067e6f4c4106"}, {"id":"5ef4664d-3600-4df9-a6a9-01ffb0f49422"}, {"id":"6dc95c01-742e-4225-8298-e5750fe67f27"}]'
I am new to linux shell script. i want that my script read a property file and save the value in any variable , the same which i can pass in same script..
as i wrote script is not fulfilling my requirement:
!/bin/bash
. test1
flat
if [ "$1" == test1 ]; then
flat=$1; /assign value to var flat
echo "flat"
fi
test1 is property file which includes :
la=12
tu=15
now i want when i run:
./myscript la
it read it from property file and store the value in flat variable.
Please help me.
You just need to use indirect referencing, but to do so, you need to store the value of the special parameter $1 in a regular parameter first.
!/bin/bash
. test1
var="$1"
# Only assign to flat if the variable specified in var is defined
if [ -n "${!var:-}" ]; then
flat="${!var}"; # assign value to var flat
echo "flat"
fi
First, ${!var} expands to the value of the variable whose name is in var. If var is "foo", it's the same as $foo. If var is "baz", it's the same as $baz.
${var:-default} expands to the value of var if it is set and has a non-null value. Otherwise, it expands to whatever you have after the ':-', in this case the string default. If there is no string, it uses the null value. So ${var:-} would expand to the null string if var was not set (or was already the null string).
Combining the two, ${!var:-} takes the variable var, and uses its value as a variable name. It then tries to expand that variable, and if it isn't set or is null, expand to the null string. So if var is la, it expands to the value of la. If var is re, and there is no variable re set, it expands to the null string.
Finally, the -n operator tests if its argument is non-zero length. In other words, it checks that the result of trying to expand the variable whose name is in var is not the null string. If that's true, then expand it again (yes, it's a little redundant) and assign its value to flat.
As the answer is written above, the variable flat is undefined if the argument to the script is not the name of a variable set in test1. If you don't mind flat being set regardless (say, flat=""), you don't need the if statement. You can just use one line to set the value of flat:
#!/bin/bash
. test1
var="$1"
flat="${!var:-}"
If I understood correctly you want to achieve an indirect variable dereferencing (see e.g. this example).
The solution is to use eval:
eval flat=\$$1