What is ${command_} in a shell script - shell

I have googled and found nothing. I am reading a shell script file and there there is this line
echo "docker run command"
echo ${command_}
What does this mean? Please notice that
there is an underscore after "command"
command_ seems not to be defined elsewhere

What is ${command_} in a shell script
${command_} means to expand the variable named command_ to it's value.
What does this mean?
echo "docker run command" - means to execute the command echo (possibly a builtin) with one argument docker run command.
echo ${command_} - means to execute the command echo (possibly a builtin) with the result of expansion of the variable command_ will undergo word splitting expansion and then the result will be passed as arguments to the echo command.
there is an underscore after "command"
It doesn't matter - underscore is nothing special.
command_ seems not to be defined elsewhere
That means that ${command_} expansion will expand to an empty string, and the second echo will run with no arguments.

echo command is used to print the arguments passed. But if argument has $ to it, it means it evaluates its value and prints the same.
Here, you shell script would be having a variable named "command_". It'll just find its value, if defined, and print it. If its not defined, nothing will be printed.

Related

Unexpected behavior of the unix echo command

while writing some script i found the following issue ,
suppose
set x = "param[xyz]";
echo $x
the output was echo:No match
But when i do ,
echo "$x"
i got the output: param[xyz]
so echo is doing a two way substitution ,
Initially echo $x was converted to echo param[xyz] and then it tried to look for the param[xyz] value .
But Ideally it should have just printed the variable whatever provided to it .
Does this behavior is a valid use case?
echo does no substitution at all, it's the shell that does it. It depends on the shell you use, but it seems that you are using a shell of the family of c-shells. Shell expands variables in the command line, so the first step is to generate:
[csh] echo param[xyz]
and then the shell does file match expansion, but as there is no file that correspond to the pattern the shell answers that there is no match. The message is somehow misleading as the shell reminds you what "command" was concerned not that the command failed by itself.
In the second try, enclosing the variable inside " prevent the shell to do other expansion and the shell launch the command with the argument obtained after the first expansion.
There exists another prevention if you use ', the shell won't ever expand variables:
[csh] echo '$x'
$x
Please refer to shell documentation and especially about expansion.
Another experience to convince you is to try with an non existing command:
[csh] weirdo z*
weirdo: No match
which is different than an non existing command:
[csh] weirdo
weirdo: Command not found.
If you'd use other shell behavior would be different:
[bash] echo z*
z*
because that shell produces as the argument the string itself in the case file matching is not working.
With:
[zsh] echo z*
zsh: no matches found: z*
the behavior is much more similar to c-shells but the message is much more clear, the shell failed at matching.

what is the meaning of FOOBAR=foobar followed by a shell command?

I see in shell scripts a variable assignment followed (without a semicolon) by a command. What is the meaning of that? It does not seem to affect this command, and it does not seem to affect the next command the way normal assignment would:
>echo $FOOBAR
>FOOBAR=1 echo $FOOBAR
>echo $FOOBAR
>
So, what does it do?
It sets that environment variable to that value only for that process.
Here, step by step, is what happens:
Original command: FOOBAR=1 echo $FOOBAR
Shell performs substitution: command is now FOOBAR=1 echo
Shell fork(2)s a new process
Environment variable is created in the new process: command is now echo (with $FOOBAR equal to 1)
New process is exec(3)ed: \n is output
New process exits and is reaped by the shell
At no point does the parent process see the assigned value of $FOOBAR.
On first run of echo $FOOBAR you will get empty result on your screen as the FOOBAR variable is not set yet.
Then when you set it to 1,and run it on the second time it will display 1.
Note: This value will be lost when you close your terminal where you wrote these. $ notation in shell and shell scripting in Unix like environments simply denotes a variable.
What happens in your case in second command i.e FOOBAR=1 echo $FOOBAR is that the line is not syntactically incorrect but it breaches the contract of equalto(=) which actually does not accept a space thus no error is thrown and FOOBAR=1 is just treated as a parameter and it fails while the command for echo executes successfully.
I would suggest try this :
FOOBAR=1
echo $FOOBAR
in different lines or
FOOBAR=1 ; echo $FOOBAR in one line.

Run a bash including a variable in the "bash XXX.sh" command

I am completely new to "programming" in Linux, and I wonder if it is possible to include the definition of a variable when I run a bash file.
My bash file needs the variable in order to go from one or another path, so I would like to be able to include it when running the script.
Something like this:
bash MYFILE.sh -VARIABLE
So the -VARIABLE would be used in the script.
Thank you!
You can take advantage of shell parameter expansion to smoothly read variables from the environment of the parent process, if it's that what you want to achieve.
Look at the following script named test.sh:
#!/bin/bash
VARIABLE=${VARIABLE:="default value"}
echo $VARIABLE
If you start it with the line
$ ./test.sh
it outputs
default value
But if you invoke test.sh with the line
$ VARIABLE="custom Value" ./test.sh
it outputs
custom value
But make sure that the variable assignment is at the beginning of the line. Otherwise it is passed to test.sh as command line argument.
The used form of parameter expansion ${parameter:=word} is described in the bash reference manual as:
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.

Bash command line arguments, replacing defaults for variables

I have a script which has several input files, generally these are defaults stored in a standard place and called by the script.
However, sometimes it is necessary to run it with changed inputs.
In the script I currently have, say, three variables, $A $B, and $C. Now I want to run it with a non default $B, and tomorrow I may want to run it with a non default $A and $B.
I have had a look around at how to parse command line arguments:
How do I parse command line arguments in Bash?
How do I deal with having some set by command line arguments some of the time?
I don't have enough reputation points to answer my own question. However, I have a solution:
Override a variable in a Bash script from the command line
#!/bin/bash
a=input1
b=input2
c=input3
while getopts "a:b:c:" flag
do
case $flag in
a) a=$OPTARG;;
b) b=$OPTARG;;
c) c=$OPTARG;;
esac
done
You can do it the following way. See Shell Parameter Expansion on the Bash man page.
#! /bin/bash
value=${1:-the default value}
echo value=$value
On the command line:
$ ./myscript.sh
value=the default value
$ ./myscript.sh foobar
value=foobar
Instead of using command line arguments to overwrite default values, you can also set the variables outside of the script. For example, the following script can be invoked with foo=54 /tmp/foobar or bar=/var/tmp /tmp/foobar:
#! /bin/bash
: ${foo:=42}
: ${bar:=/tmp}
echo "foo=$foo bar=$bar"

What is the meaning of a question mark in bash variable parameter expansion as in ${var?}?

What is the meaning of a bash variable used like this:
${Server?}
It works almost the same as (from the bash manpage):
${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.
That particular variant checks to ensure the variable exists (is both defined and not null). If so, it uses it. If not, it outputs the error message specified by word (or a suitable one if there is no word) and terminates the script.
The actual difference between that and the non-colon version can be found in the bash manpage above the section quoted:
When not performing substring expansion, using the forms documented below, bash tests for a parameter that is unset or null. Omitting the colon results in a test only for a parameter that is unset.
In other words, the section above can be modified to read (basically taking out the "null" bits):
${parameter?word} Display Error if Unset. If parameter is 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.
The difference is illustrated thus:
pax> unset xyzzy ; export plugh=
pax> echo ${xyzzy:?no}
bash: xyzzy: no
pax> echo ${plugh:?no}
bash: plugh: no
pax> echo ${xyzzy?no}
bash: xyzzy: no
pax> echo ${plugh?no}
pax> _
There, you can see that while both unset and null variable result in an error with :?, only the unset one errors with ?.
It means that the script should abort if the variable isn't defined
Example:
#!/bin/bash
echo We will see this
${Server?Oh no! server is undefined!}
echo Should not get here
This script will print out the first echo, and the "Oh no! ..." error message.
See all the variable substitutions for bash here:
https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
As per man bash:
${parameter:?word}
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.
So if you omit word and don't pass $1 to your function or shell script then it will exit with this error:
-bash: 1: parameter null or not set
However you can place a user-defined error to let your caller know that a required argument has not been set e.g.:
local arg1="${1:?needs an argument}"
It will continue running script/function only if $1 is set.
:? causes the (non-interactive) shell to exit with an error message if given parameter is null or unset. The script you are looking at is omitting the error message; usually, you'd see something like
foo=${1:?Missing first argument}
For example,
$ foo=${1:?Missing first argument}
bash: 1: Missing first argument
$ set firstarg
$ foo=${1:?Missing first argument}
$ echo $foo
firstarg

Resources