Defining variables with indirect expansion - variables

I know that I can use indirect expansion to call variables whose names are contained in other variables as follows
VAR="test"
VARNAME="VAR"
echo ${!VARNAME}
However if I try to redefine a variable with this:
VARVALUE=0
VALUE="VARVALUE"
${!VARNAME}=${!VALUE}
echo ${!VARNAME}
It doesnt work, and I get
bash: test=0: command not found
I can see why this variable declaration fails, but I can't see how to fix it. In searching I've only found examples calling variables with indirect expansion, but not defining them so.
edit:
After a bit more searching, I've tried
eval "${!VARNAME}=${!VALUE}"
which throws
bash: =0: command not found

Fiddling with it some more, I've managed to find a solution
eval "$VARNAME=${!VALUE}"

Related

How to pass shell variable to pig param file

How we can pass shell variable to pig param file. As an example I have a shell variable defined as DB_NAME. i would like to define my pig parameter file as
p_db_nm=$DB_NAME
I tried like above which does not work and i did try like echo $DB_NAME does not work either.
I'm aware that i can pass this by using -param in command line but i have many variables which i would like to put it in param file but the values will be defined in shell script. I searched many topics in google and didn't have any luck!!!
My question is similar what was posted in http://grokbase.com/t/pig/user/09bdjeeftk/is-it-possible-to-use-an-env-variable-in-parameters-file but i see no workable solution is posted.
Can anyone help?
you can pass parameter file using –param_file option.
if Parameter File named "pig.cfg" defined like below,
p_db_nm=$DB_NAME
in the shell, pig command will be like this,
pig -param_file pig.cfg
and finally in your pig, you can use does variables named by KEY in the cfg file. (in this case, $p_db_nm)

How do I escape a "$" in bitbake/yocto?

One of my recipes in Yocto need to create a file containing a very specific line, something like:
${libdir}/something
To do this, I have the recipe task:
do_install() {
echo '${libdir}/something' >/path/to/my/file
}
Keeping in mind that I want that string exactly as shown, I can't figure out how to escape it to prevent bitbake from substituting in its own value of libdir.
I originally thought the echo command with single quotes would do the trick (as it does in the bash shell) but bitbake must be interpreting the line before passing it to the shell. I've also tried escaping it both with $$ and \$ to no avail.
I can find nothing in the bitbake doco about preventing variable expansion, just stuff to do with immediate, deferred and Python expansions.
What do I need to do to get that string into the file as is?
Bitbake seems to have particular issues in preventing expansion from taking place. Regardless of whether you use single or double quotes, it appears that the variables will be expanded before being passed to the shell.
Hence, if you want them to not be expanded, you need to effectively hide them from BitBake, and this can be done with something like:
echo -e '\x24{libdir}/something' >/path/to/my/file
This uses the hexadecimal version of $ so that BitBake does not recognise it as a variable to be expanded.
You do need to ensure you're running the correct echo command however. Under some distros (like Ubuntu), it might run the sh-internal echo which does not recognise the -e option. In order to get around that, you may have to run the variant of echo that lives on the file system (and that does recognise that option):
/bin/echo -e '\x24{libdir}/something' >/path/to/my/file
By default this task will be executed as shell function via /bin/sh, but it depends on your system what it will be as you can have a symlink named /bin/sh pointing to bash. The BitBake's manual prevents from using bashism syntax though.
You can consider just adding this task in your recipe as python function:
python do_install () {
with open('/path/to/your/file', 'a') as file:
file.write('${libdir}/something')
}
'a' stands for append.
This should eliminate the problem with variable expansion.
There is no standard way to escape these sorts of expressions that I am aware of, other than to try to break up the expression - accordingly this should work:
do_install() {
echo '$''{libdir}/something' >/path/to/my/file
}
The best solution is simply this:
bitbake_function() {
command $libdir/whatever
}
Bitbake will only expand ${libdir}; $libdir is passed through verbatim.
We don't have to worry about dollar signs that are not followed by {, and in this case, there is no need for libdir to be wrapped in braces.
The only time we run into a problem with just $foo is if we have something like ${foo}bar where the braces are required as delimiters so that bar isn't included into the variable name. In that situation, there are other solutions, such as for instance generating the shell syntax "$foo"bar. This is less cryptic than resorting to \x24.
If you need to use $ in variable assignment, remember that bitbake won't evaluate $whatever so you have to escape it for the underlying shell.
For instance I set gcc/ld Rpath option to use $ORIGIN keyword this way:
TARGET_LDFLAGS_append = " -Wl,-rpath-link=\\$$ORIGIN"
https://lists.yoctoproject.org/pipermail/yocto/2017-September/037820.html
You can define a variable to be a literal dollar sign.
DOLLAR = "$"
do_install() {
echo '${DOLLAR}{libdir}/something' >/path/to/my/file
}
no extra quoting required.

How exactly do you use variables in Jenkins?

Can someone concisely explain what the differences between the three variables below are? Because in all honesty, when I create a Jenkins job, I randomly guess between the three types until something works, but I'd love to understand rather than blindly picking.
${ENV,var="BUILD_USER"}
${BUILD_USER}
$BUILD_USER
Also, are there other ways of writing variables in Jenkins that I missed other than the 3 ways above?
When used in a statement:
${ENV,var="BUILD_USER"}--evaluates the system environment variables and returns the value for the variable BUILD_USER.
example: curl ${ENV,var="BUILD_USER"}/api/xml
${BUILD_USER} --returns the value of the BUILD_USER variable in the current script memory space.
example: curl ${BUILD_USER}/api/xml
$BUILD_USER--used to assign values to the BUILD_USER variable.
example: $BUILD_USER = "BUILD_USER"
In general, variable expansion is up to the plugin that interprets a configuration value.
For example, if you set up a job parameter GIT_REPOSITORY and use it to configure an address where git clone should go by putting $GIT_REPOSITORY into the git repository field, it works, but only because the Jenkins git plugin has implemented variable expansion support.
Many plugins do implement it but you cannot know it unless you test it. However, these days the support is so common it is safe to assume it should work.
Both forms of reference, $VAR and ${VAR}, work and are equivalent. The latter form is useful if you need to use the variable in a place where it is surrounded by other characters that could be interpreted as part of variable, like $VARX (Jenkins would be looking for variable named VARX) and ${VAR}X (Jenkins understands the variable is named VAR).
These rules have been modeled after variable expansion rules in Unix shells. Indeed, the job variables are made available as environment variables to build steps and in the Unix shell build step the variables are used the same way as above.
In a Windows CMD build step the variables are again used like any Windows environment variable: %VAR%.

Use environment variables as default for cmake options

I would like to set up a cmake script with some options (flags and strings). For some of the options I would like to use environment variables as a default. Basically, I'm trying to emulate something like MY_OPTION ?= default in a Makefile. I tried the following:
project (Optiontest)
option(MY_OPTION
"Documentation"
$ENV{MY_OPTION}
FORCE)
message("value: ${MY_OPTION}")
I called this in the following way:
$ cmake -DMY_OPTION=ON .
value: ON
$ cmake -DMY_OPTION=OFF .
value: OFF
$ MY_OPTION=OFF cmake .
value: OFF
$ MY_OPTION=ON cmake .
value: OFF
My problem is that the last line should be ON as well.
For bonus karma: I would actually prefer three levels of preference. The value of -DMY_OPTION should be used if given. If not, the value of a set environment variable MY_OPTION should be used. If this is also not set, a constant should be used. I guess, I could use a bunch of nested if statements and somehow check if the variables are set, but I don't know how and I hope there is a better way.
FORCE is (as of CMake 3.0.2) not a valid parameter for option.
This is the primary source of problems. CMake will interpret the string FORCE as the desired initial value of the option in absence of an environment variable. The usual contrived rules for string-to-truth-value-conversion apply, resulting in the option being set to OFF by this call.
Second, you need to account for the fact that the environment variable is not set. Your current code misses to handle that case properly. $ENV{MY_OPTION} will evaluate to the empty string in that case. If you evaluate the set values in both the cache and the environment, you can enforce any behavior that you want.
In general, you should think about what you actually want here. Usually, FORCE setting a cached variable is a bad idea and I would not be surprised if you found your initial argument for doing this flawed after some careful reevaluation.
Maybe value of MY_OPTION cached in CMake cache? Do you try to clean cmake cache after third call MY_OPTION=OFF cmake .?

Space in path in a shell script

I have a variable
android="/media/New Volume_/android-sdk-linux_86"
I get an error saying that it cannot find the directory
I changed it to android="/media/New\ Volume_/android-sdk-linux_86"
I still get the same error. I even tried
android="/media/'New Volume_'/android-sdk-linux_86"
and I am using "$android" everywhere ...
I am not able to find the error, can someone help me..
Thanks
Take it this is bash? You assign variables with spaces like this:
android="/media/New Volume_/android-sdk-linux_86"
(Note you don't use the $ notation when setting a value.)
And reference them like this:
cd "$android"