Variable inside a square bracket in Bash [duplicate] - bash

This question already has answers here:
Purpose of square brackets in shell scripts
(3 answers)
How to use double or single brackets, parentheses, curly braces
(9 answers)
Closed 4 years ago.
What does it mean to have a variable inside square brackets? Boolean?
For example:
[ $FILES ] || { print "File not found." }
[ $VERIFY ] && { print "file verification fail" }

[] invokes the test command which allows you to run conditional tests based on what arguments you supply inside them.
For the examples you have supplied:
$FILES is a single argument, so the test will return True if the argument is not null. Piped with || (Logical OR), whenever $FILES is 'null', test will return a non-zero exit status (1) thus printing "File not found."
Ditto for $VERIFY except being piped with && means that print "file verification" will execute as long as $VERIFY is not null (as test will return a status of 0 in this case).
I will also add that there also exists [[]] which is the 'newer' test and is more commonly used
EDIT: I would also recommend enclosing variable names in double quotes ("") as they are technically arguments to a command.

Related

Bash, reading string into variable results in reading command into variable with used logically [duplicate]

This question already has answers here:
How do I set a variable to the output of a command in Bash?
(15 answers)
Closed 9 months ago.
I have a file that contains a number. I want to read this number into a variable and then use it in an if statement. I am using the following command to populate the variable:
step='cat ./update_step'
The file, update_step has a single number stored in it. The number can be 0, 1, 2, 3, 4, or 5. For the sake of this example, the file contains the number "0".
if I check the variable as so:
$step
Then I get "0" as a return; which is expected.
But then if I try to use $step in an if statement like:
if [ $step -eq 0 ]
then
echo "this is an integer"
fi
I get a, "too many arguments" error.
If I check the variable with echo:
echo "$step"
Then the variable returns "cat ./update_step"
How do I read in the number that is stored in update_step as an integer (honestly it could even be a string at this point) so that I can use it with an if statement?
Try
step=$(cat ./update_step)
echo $step

Difference between 'if [ "x$foo" = "x1" ]' vs 'if [ "$foo" = "1" ]' in bash? [duplicate]

This question already has answers here:
Why do shell script comparisons often use x$VAR = xyes?
(7 answers)
Closed 3 years ago.
I'm reading Gitlab's source code to learn more about how it works. In the run bash script located inside the project root directory, I see the following:
if [ "x$GDK_RUNIT" = "x1" ]; then
...
fi
I know this conditional's purpose is to check if the value of the GDK_RUNIT envar is set equal to 1, and to exit with a non-zero return code if that's the case. My question is, what is the difference between the above code and the following:
if ["$GDK_RUNIT" = "1" ]; then
...
fi
In other words, what is the purpose of placing "x" before both the envar name and "1"?
I checked man test for anything related to x (since I know if and test are functionally equivalent), but all I saw was the -x flag.
x$GDK_RUNIT doesn't look like a flag to me, so I assumed the contents of the man page wasn't relevant.
It's completely unnecessary. There are old implementations of test which cannot handle an empty argument, so if GDK_RUNIT is undefined or empty, it avoids the equivalent of [ "" = "1" ], replacing it with [ "x" = "x1" ] instead. Just about any character or string would work in place of x, but the use of x was conventional.
However, no reasonably modern implementation, and certainly not bash's, has this problem.

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.

How can I write if/else with Boolean in Bash? [duplicate]

This question already has answers here:
How can I declare and use Boolean variables in a shell script?
(25 answers)
Closed 5 years ago.
How can I write an 'if then' statement to switch between these to variables as in the following?
if(switch){
server_var_shortname=$server_shared_shortname
server_var=$server_shared
server_var_bare=$server_shared_bare
} else {
server_var_shortname=$server_vps_shortname
server_var=$server_vps
server_var_bare=$server_vps_bare
}
I'm not familiar with Bash syntax and basically just need an 'if/else' statement on a Boolean. Also, can I use true / false values as such? Also how do I do the 'else' statement?
$switch=true;
if $switch
then
server_var_shortname=$server_shared_shortname
server_var=$server_shared
server_var_bare=$server_shared_bare
fi
First, shells (including Bash) don't have Booleans; they don't even have integers (although they can sort of fake it). Mostly, they have strings.
Bash also has arrays... of strings. There are a number of ways of faking Booleans; my favorite is to use the strings "true" and "false". These also happen to be the names of commands that always succeed and fail respectively, which comes in handy, because the if statement actually takes a command, and runs the then clause if it succeeds and the else clause if it fails. Thus, you can "run" the Boolean, and it'll succeed if set to "true" and fail if set to "false". Like this:
switch=true # This doesn't have quotes around it, but it's a string anyway.
# ...
if $switch; then
server_var_shortname=$server_shared_shortname
server_var=$server_shared
server_var_bare=$server_shared_bare
else
server_var_shortname=$server_vps_shortname
server_var=$server_vps
server_var_bare=$server_vps_bare
fi
Note that the more usual format you'll see for if has square-brackets, like if [ something ]; then. In this case, [ is actually a command (not some funny sort of grouping operator) that evaluates its argument as an expression; thus [ "some string" = "some other string" ] is a command that will fail because the strings aren't equal. You could use if [ "$switch" = true ]; then, but I prefer to cheat and use the fake Boolean directly.
Caveat: if you do use the cheat I'm suggesting, make sure your "Boolean" variable is set to either "true" or "false" -- not unset, not set to something else. If it's set to anything else, I take no responsibility for the results.
Some other syntax notes:
Use $ on variables when fetching their values, not when assigning to them. You have $switch=true; up there, which will get you an error.
Also, you have a semicolon at the end of that line. This is unnecessary; semicolons are used to separate multiple commands on the same line (and a few other places), but they aren't needed to end the last (/only) command on a line.
The [ command (which is also known as test) has a kind of weird syntax. Mostly because it's a command, so it goes through the usual command parsing, so e.g. [ 5 > 19 ] is parsed as [ 5 ] with output sent to a file named "19" (and is then true, because "5" is nonblank). [ 5 ">" 19 ] is better, but still evaluates to true because > does string (alphabetical) comparisons, and "5" is alphabetically after "19". [ 5 -gt 19 ] does the expected thing.
There's also [[ ]] (similar, but cleaner syntax and not available in all shells) and (( )) (for math, not strings; also not in all shells). See Bash FAQ #31.
Putting commands in variables is generally a bad idea. See Bash FAQ #50.
shellcheck.net is your friend.
Bash doesn't have any concept of Boolean - there are no true / false values. The construct
[ $switch ]
will be true except when switch variable is not set or is set to an empty string.
[ ] && echo yes # Nothing is echoed
[ "" ] && echo yes # Nothing is echoed
unset switch && [ $switch ] && echo yes # Nothing is echoed
switch=1 && [ $switch ] && echo yes # 'yes' is echoed
switch=0 && [ $switch ] && echo yes # 'yes' is echoed - the shell makes no distinction of contents - it is true as long it is not empty
See also:
How can I declare and use Boolean variables in a shell script?
Here is a good guide for If else. But I want to show a different approach (which you will find also in the link on page 3).
Your coding looks like JavaScript, so I think with Switch you could also mean the case command instead of if. Switch in JavaScript is similar to case within a shell, but there isn't any method to check for Booleans. You can check string values for like true and false, and you can check for numbers.
Example...
#!/bin/bash
case "$Variable" in
false|0|"")
echo "Boolean is set to false."
;;
*)
echo "Boolean is set to true."
;;
esac
Addition
Keep in mind, there are many programs and tools that uses Boolean values in different forms.
Two examples...
SQL in general uses numbers as Boolean.
JavaScript uses true and false values.
Meaning: Your Bash script has to know the format of Booleans, before processing them!
You need something like this:
if
CONDITION_SEE_BELOW
then
server_var_shortname=$server_shared_shortname
server_var=$server_shared
server_var_bare=$server_shared_bare
else
server_var_shortname=$server_vps_shortname
server_var=$server_vps
server_var_bare=$server_vps_bare
fi
In Bash (and other shells), the CONDITION_SEE_BELOW part has to be a command. A command returns a numerical value, and by convention 0 means "true" and any non-zero value means "false". The then clause will execute if the command returns 0, or the else clause in all other cases. The return value is not the text output by the command. In shells, you can access it with the special variable expansion $? right after executing a command.
You can test that with commands true and false, which do one thing: generate a zero (true) and non-zero (false) return value. Try this at the command line:
true ; echo "true returns $?"
false ; echo "false returns $?"
You can use any command you want in a condition. There are two commands in particular that have been created with the idea of defining conditions: the classic test command [ ] (the actual command only being the opening bracket, which is also available as the test command), and the double-bracketed, Bash-specific [[ ]] (which is not technically a command, but rather special shell syntax).
For instance, say your switch variable contains either nothing (null string), or something (string with at least one character), and assume in your case you mean a null string to be "false" and any other string to be "true". Then you could use as a condition:
[ "$switch" ]
If you are OK with a string containing only spaces and tabs to be considered empty (which will happen as a result of standard shell expansion and word splitting of arguments to a command), then you may remove the double quotes.
The double-bracket test command is mostly similar, but has some nice things about it, including double-quoting not being needed most of the time, supporting Boolean logic with && and || inside the expression, and having regular expression matching as a feature. It is, however a Bashism.
You can use this as a reference to various tests that can be performed with both test commands:
6.4 Bash Conditional Expressions
If at all interested in shell programming, be sure to find out about the various tests you can use, as you are likely to be using many of them frequently.
As addition to Gordon's excellent answer, in Bash you can also use the double-parentheses construct. It works for integers, and it is the closest form to other languages. Demo:
for i in {-2..2}; do
printf "for %s " "$i"
if (( i )) # You can omit the `$`
then
echo is nonzero
else
echo is zero
fi
done
Output:
for -2 is nonzero
for -1 is nonzero
for 0 is zero
for 1 is nonzero
for 2 is nonzero
You can use any arithmetic operations inside, e.g.:
for i in {1..6}; do
printf "for %s " "$i"
if (( i % 2 )) #modulo
then
echo odd
else
echo even
fi
done
Output
for 1 odd
for 2 even
for 3 odd
for 4 even
for 5 odd
for 6 even

Compare a Bash string literal to a local variable

#!/bin/bash
function getComment(){
local lang=$1;
local theComment=$2;
if [$lang == "Java"] #Surprisingly, an error occurs here: prog.sh: line 6: [Java: command not found
then
echo "//"$theComment; return;
else
echo "Language not found!"; return;
fi
}
getComment "Java" "Whoo!";
exit $?
I'm writing a Bash script that compares a variable to a string literal, and I'm using [$lang == "Java"] (as shown above) to compare the value of lang to "Java". However, this comparison produces the following error:
stderr:
prog.sh: line 6: [Java: command not found
I've tried using [$lang -eq "Java"] and ($lang -eq "Java") as well, but those statements didn't work either, and they produced exactly the same error.
Why is this error occurring, and what is the correct way to compare a local variable to a string literal?
You need spaces around [ and ]:
if [ "$lang" = "Java" ]
[ is a command (it's a synonym for test), and like any other command you delimit the parameters with spaces.
You should also put variables in double quotes, in case the value is empty or contains whitespace or wildcard characters.
Finally, the operator to perform string comparison is =, although some versions of test allow == as an extension.
First, you have to enclose the variable between double quotes, because the variable could have some spaces or special characters.
Finally remember that "[" it's an executable by itself (usually is in /bin).
if [ "$lang" == "Java" ]; then
First thing is, don't use [ ] - it's better to use [[.
And second - you need to add some spaces:
if [[ $lang == Java ]]

Resources