This question already has answers here:
What does "plus colon" ("+:") mean in shell script expressions?
(4 answers)
Closed 5 years ago.
I have a bash script that uses the following syntax:
if [ ! -z ${ARGUMENT+x} ]; then
What is the meaning of the "+x" syntax after the argument name?
It means that if $ARGUMENT is set, it will be replaced by the string x
Let's try in a shell :
$ echo ${ARGUMENT+x}
$ ARGUMENT=123
$ echo ${ARGUMENT+x}
x
You can write this with this form too :
${ARGUMENT:+x}
It have a special meaning with :, it test that variable is empty or unset
Check bash parameter expansion
Rather than discussing the syntax, I'll point out what it is attempting to do: it is trying to deterimine if a variable ARGUMENT is set to any value (empty or non-empty) or not. In bash 4.3 or later, one would use the -v operator instead:
if [[ -v ARGUMENT ]]; then
Related
This question already has answers here:
Assigning default values to shell variables with a single command in bash
(11 answers)
Closed 2 years ago.
I understand the empty string in Bash is falsy, and we should be able to use something like
a=""
b=($a || 0)
which means if $a is falsy, then just make it 0. But it gave
bash: syntax error near unexpected token `||'
and I understand we can use [-z $a] and use the Bash ternary form:
a=""
[[ -z $a ]] && b=0 || b=$a
But is there a way to use something similar to the first form above that works in both Bash and Zsh?
You can use parameter expansion: ${PARAMETER:-WORD} will, if the variable PARAMETER is unset or an empty string, evaluate to WORD, otherwise the value of PARAMETER.
So:
b=${a:-0}
This question already has an answer here:
Why isn't tilde (~) expanding inside double quotes? [duplicate]
(1 answer)
Closed 4 years ago.
Consider the following Bash script:
function dosomething {
local fname="~/.bash_profile"
if [[ -f "$fname" ]]; then
echo "proceeding"
else
echo "skipping"
fi
}
dosomething
I always get "skipped" although I know that ~/.bash_profile exists. Why?
~ is only expanded by the shell if it's unquoted. When it's quoted it's a literal tilde symbol.
local fname=~/.bash_profile
This question already has answers here:
How to check if a variable is set in Bash
(38 answers)
Closed 5 years ago.
I've come across code that uses this syntax in an if condition:
if [ ! -z ${VARIABLE+x} ]; then
some commands here
fi
Does it test for an non-empty variable? If so, how is it different from ! -z "$VARIABLE"?
See PARAMETER EXPANSION in man bash:
${parameter:+word}
Use Alternate Value. If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.
And few paragraphs above in the same section:
Omitting the colon results in a test only
for a parameter that is unset.
This question already has answers here:
Indirect variable assignment in bash
(7 answers)
What is indirect expansion? What does ${!var*} mean?
(6 answers)
Closed 6 years ago.
I have the following test.sh script:
#!/bin/bash
foo=0
bar=foo;
${bar}=1
echo $foo;
Output:
./test.sh: line 4: foo=1: command not found
0
Why the "command not found" error? How to change script to "echo $foo" outputs 1?
That's not the way to do indirection unfortunately. To do what you want you could use printf like so
printf -v "$bar" "1"
which will store the value printed (here 1 in the variable name given as an argument to -v which when $bar expands here will be foo
Also, you could use declare like
declare "$bar"=1
which will do variable substitution before executing the declare command.
In your attempt the order of bash processing is biting you. Before variable expansion is done the line is split into commands. A command can include variable assignments, however, at that point you do not have a variable assignment of the form name=value so that part of the command is not treated as an assignment. After that, variable expansion is done and it becomes foo=1 but by then we're done deciding if it's an assignment or not, so just because it now looks like one doesn't mean it gets treated as such.
Since it was not processed as a variable assignment, it must not be treated as a command. You don't have a command named foo=1 in your path, so you get the error of command not found.
You need to use the eval function, like
#!/bin/bash
foo=0
bar=foo;
eval "${bar}=1"
echo $foo;
The ${bar}=1 will first go through the substitution process so it becomes foo=1, and then the eval will evaluate that in context of your shell
This question already has answers here:
Strange behavior of argv when passing string containing "!!!!"
(3 answers)
Closed 5 years ago.
Why does this command line work:
$ output='Irrelevant'; if [[ $output =~ Something ]]; then echo "I found something in the output." ; fi
And this one give me a strange parse error?
$ output='Irrelevant'; if [[ $output =~ Something ]]; then echo "I found something in the output!" ; fi
-bash: !": event not found
The only change from the first version is that the sentence to be echoed inside quotes ends with an exclamation mark. Why does Bash give me that error in the second version?
In case it matters, this is the output from bash --version:
GNU bash, version 4.2.24(1)-release (x86_64-pc-linux-gnu)
You can wrap the string in single quotes instead of double quotes.
The exclamation point invokes the very useful history expansion function described in the bash manual.
History expansions are introduced by the appearance of the history expansion character, which is ! by default. Only \ and ' may be used to escape the history expansion character.
For instance, to execute the last command that started with the word mysql type this:
!mysql
or to execute the last command containing the word grep, type this:
!?grep
The bash manual also documents the syntax of the history expansion operators.