Difference between using "set" and not using set for variables? In Cygwin. - variables

I don’t understand the difference between:
set youtube=’https://youtube.com’
and
youtube=’https://youtube.com’
With the second one, I’m able to use it in the middle of a command, such as:
cygstart $youtube
and that works.
Why and how are these different? They both set variables?
And, when I don't use the word "set" I have to expand the variable using $?
Thanks.

The two commands are completely unrelated; set youtube='https://youtube.com' has nothing to do with $youtube. What it does is, it sets $1 to the whole string 'youtube=https://youtube.com'.
Per http://www.gnu.org/software/bash/manual/bashref.html#The-Set-Builtin, set is a shell builtin with three distinct purposes:
If you don't give it any options or arguments, it prints out all the existing shell variables and functions.
It has various options that let you change various properties of the shell. For example, set -C tells the shell that you don't want > to overwrite existing files (and that you instead want commands to fail if they would otherwise do that); and set +C tells the shell that never mind, you now want > to be able to overwrite files again.
Any arguments, other than options, replace the positional parameters ($1 and $2 and so on, as well as $# and $*).
Since set youtube='https://youtube.com' calls set with exactly one argument, namely youtube=https://youtube.com, it has the effect of setting the first positional parameter ($1) to youtube=https://youtube.com.
Note that youtube='https://youtube.com' is a somewhat misleading way to write youtube=https://youtube.com; the single-quotes aren't doing anything here (since the sole purpose of single-quotes is to escape whitespace and special characters, and https://youtube.com doesn't have any of these).

Related

How to launch make while appending a list of values to a variable?

In my Makefile I have defined a variable
VAR = -Ddef1 -Ddef2 -Ddef3
I'd like to launch make like this
make VAR+=-Ddef4 -Ddef5
But the space messes things up. How can I set VAR to a list of values, like it's possible to do inside the Makefile? Thanks for tips.
In your Makefile:
VAR = -Ddef1 -Ddef2 -Ddef3 $(EXTRAVAR)
On the command line:
make EXTRAVAR="-Ddef4 -Ddef5"
As frequently with the shell, tokens with spaces must be quoted. On the command line make FOO+= does the same as make FOO=. It does not append, it overwrites (in your case). Thus the trick with a second variable EXTRAVAR.

Handling Constants and variables in shell script

I have the following code in my script. There are 50 more commands like this:
"SELECT date, count(*) FROM ttc_table....date_sub(current_date, **30**)" > **/path/location/file1.txt**
"SELECT date, count(*) FROM ascc_table....date_sub(current_date, **30**)" > **/path/location/file2.txt**
"SELECT date, count(*) FROM bmtc_table....date_sub(current_date, **30**)" > **/path/location/file3.txt**
I want to create constant for value 30 and have a variable for filepath.
What is the best approach?
The comment by #Arminius answers actually half of the question, the one about variables, and it is specific to bash.
Since you have tagged the question as shell, I assume that you are searching an answer which works on POSIX shells. This means:
(1) While many of the variable substitions explained in the document by Arminius work in POSIX shell too, be aware that not all do.
(2) You also asked about defining a constant. In POSIX shell, it is AFIK not possible to define a constant. If you really need this, you have to switch to a different shell - for instance Zsh or bash. Note that in these shells, constants are actually called readonly variables.

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%.

Variable assignment in batch

This question seems to be (very) stupid be I can't deal with it :(
When I tried this batch code:
if "%1" == "-i" (
set is = %2
echo. %is%
shift
)
called with 2 (or more) arguments, it does NOT work. It actually prints a blank. The "shift" command is not done either. When I watch the executed code (without the #echo off at the beginning), I can see that the "set" command is completed.
What's wrong with it?
Example of calling:
c:\script.bat -i test -d bla
You have two issues. By default group of statements in parens will have variable expansion done all at once, that is before your set command. Also the semantics for set is wrong, you don't want spaces around the =.
Add this to the top of your file:
setlocal ENABLEDELAYEDEXPANSION
and remove the spaces around = in set:
set is=%2
Finally used delayed expansion:
echo. !is!
A possible third issue is you may need two SHIFTs, one for -i, one for it's is argument.
Update
Thanks to #dbenham for pointing out that it wasn't a syntax error with set, it's just surprising behavior that deserves a little explanation. If you execute these commands:
set a=one
echo "%a%"
The result is:
"one"
That makes sense, but try:
set b = two
echo "%b%"
And you get:
"%b%"
What? This is what you would expect when environment var b is unset. But we just set it. Or did we:
echo "%b %"
Displays:
" two"
For the Windows set command, unlike any other language or environment I'm aware of, the spaces are significant. The spaces before the = become part of the environment var name, spaces after become part of the value. This uncommon behavior is a common source of errors when writing Windows batch programs.