how to understand - and := in bash? - bash

JOBS=${JOBS:="-j2"}
dir=${1-/usr/src}
What does := and - mean here?
I can guess they serve as some kind of default , what's the difference then?

For := (and the related =), you can use the built-in ':' command to just evaluate the parameter without having to assign it to itself:
# Set JOBS=-j2 if JOBS is not set or equal to ""
: ${JOBS:='-j2'}
# Set JOBS=-j2 if JOBS is not set. Don't change if JOBS is already set to ""
: ${JOBS='-j2'}
For :- and -, don't change the value of the variable; just use the second value in its place:
# Set dir to /usr/src if $1 is not set, but don't set $1 itself
dir=${1-/usr/src}
# Set dir to /usr/src if $1 is not set or set to "", but don't set or change $1
dir=${1:-/usr/src}

man bash (the Parameter Expansion section) will answer these and related questions.
Excerpt:
${parameter:-word}
Use Default Values. If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parame‐
ter is substituted.
${parameter:=word}
Assign Default Values. If parameter is unset or null, the expansion of word is assigned to parameter. The value of
parameter is then substituted. Positional parameters and special parameters may not be assigned to in this way.
${parameter:?word}
Display Error if Null or Unset. If parameter is null or unset, the expansion of word (or a message to that effect if word
is not present) is written to the standard error and the shell, if it is not interactive, exits. Otherwise, the value of
parameter is substituted.
${parameter:+word}
Use Alternate Value. If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substi‐
tuted.

Related

How to in-line modify a variable in a shell script?

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.

What does +x mean in bash scripting [duplicate]

This question already has answers here:
What does "plus colon" ("+:") mean in shell script expressions?
(4 answers)
Closed 4 years ago.
What does +x mean in the below statement.
if[ -z ${FSV_ROOT+x} ]
Read up on Use Alternative Value. http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
In parameter expansion if parameter is unset or null, null shall be substituted; otherwise, the expansion of word shall be substituted. Use of the colon in the format shall result in a test for a parameter that is unset or null; omission of the colon shall result in a test for a parameter that is only unset.
So in your case:
If FSV_ROOT is set and not null, substitute x
If FSV_ROOT set but null, substitute x
If FSV_ROOT is unset, substitute null
${parameter+alt_value}: if parameter is set (to any value including null), return "alt_value" instead.
[ -z ${parameter+x} ] will return true if parameter has not been set at all. The "x" has no special meaning and could be replaced with any non-null string. It is there primarily because just [ -z $parameter ] would also return true if parameter were set to null - but it also helps to avoid a syntax error if $parameter were set to expand to more than one word, which would require quoting of the variable otherwise.
See also:
https://tldp.org/LDP/abs/html/parameter-substitution.html#PARAMALTV
http://tldp.org/LDP/abs/html/refcards.html
Do not confuse with the common use of +x with the chmod command, where it means to set the execute bit on a file.

What does the return value of removal of string from variable mean in Bash?

I would like to check what the following code really did.
"resultant_value="${original_value%/*}"
It removes a pattern, '/*', from a variable, original_value.
To check the removal had happened I checked the return value of it, like following.
original_value=''
resultant_value="${original_value%/*}"
result=$?
echo "remove 1: result = ${result} : original_value = ${original_value}, resultant_value = ${resultant_value}"
original_value='../..'
resultant_value="${original_value%/*}"
result=$?
echo "remove 2: result = ${result} : original_value = ${original_value}, resultant_value = ${resultant_value}"
The outputs are following
remove 1: result = 0 : original_value = , resultant_value =
remove 2: result = 0 : original_value = ../.., resultant_value = ..
Both return values are 0. It seems that return value from ${original_value%/*} does not care of removal of matched pattern or not.
What does the return value of removal of string from variable mean in Bash?
Thank you very much.
In bash, the return value/exit status of a variable assignment statement is defined by the following rules:
The text after the = in each variable assignment undergoes tilde
expansion, parameter expansion, command substitution, arithmetic
expansion, and quote removal before being assigned to the variable.
If any of the assignments attempts to assign a value to a readonly
variable, an error occurs, and the command exits with a non-zero
status.
If one of the expansions contained a command substitution, the exit
status of the command is the exit status of the last command
substitution performed. If there were no command substitutions, the
command exits with a status of zero.
Thus, of all different types of expansions only command substitution ($(...)) can affect the status of an assignment statement. Parameter expansions, including prefix/suffix removals, don't influence the return value in any way*.
* The only exception is the ${parameter:?error_message} - Display Error if Null or Unset version of parameter expansion when used in an interactive shell (in a non-interactive shell a failed expansion of this kind simply quits the shell).

What does ":-" do in a variable declaration?

I have been tasked with assuming control over some bash scripts, and looking through them I've come across the following notation:
INITPATH=${INITPATH:-"include"}
As far as I can tell this does something similar to a = a || b and allows the setting of a default value if the environment variable is not set?
I guess I'm just looking for some clarification on this, and whether the ":-" can be broken down or used in other contexts. I've as yet failed to come across it flicking through various Bash documentation.
From the manual:
${parameter:-word}
If parameter is unset or null, the expansion of word is substituted.
Otherwise, the value of parameter is substituted.
In your example, if INITPATH is unset/null, it's set to include.
This has most of how you can substitute
echo "$\{var}"
echo "Substitute the value of var."
echo "1 - $\{var:-word}"
echo "If var is null or unset, word is substituted for var. The value of var does not change."
echo "2- $\{var:=word}"
echo "If var is null or unset, var is set to the value of word."
echo "5-$\{var:?message}"
echo "If var is null or unset, message is printed to standard error. This checks that variables are set correctly."
echo "3 - $\{var:+word}"
echo "If var is set, word is substituted for var. The value of var does not change."

How to make a script read a value from a property file and pass it to the same script?

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

Resources