bash double bracket issue
The problem lies in your script invocation. You're issuing:
$ sudo sh if_test.sh
On Ubuntu systems, /bin/sh
is dash
, not bash
, and dash
does not support the double bracket keyword (or didn't at the time of this posting, I haven't double-checked). You can solve your problem by explicitly invoking bash
instead:
$ sudo bash if_test.sh
Alternatively, you can make your script executable and rely on the shebang line:
$ chmod +x if_test.sh
$ sudo ./if_test.sh
Also note that, when used between double square brackets, ==
is a pattern matching operator, not the equality operator. If you want to test for equality, you can either use -eq
:
if [[ "14" -eq "14" ]]; then
echo "FOO"
fi
Or double parentheses:
if (( 14 == 14 )); then
echo "FOO"
fi
Are double square brackets [[ ]] preferable over single square brackets [ ] in Bash?
[[
has fewer surprises and is generally safer to use. But it is not portable - POSIX doesn't specify what it does and only some shells support it (beside bash, I heard ksh supports it too). For example, you can do
[[ -e $b ]]
to test whether a file exists. But with [
, you have to quote $b
, because it splits the argument and expands things like "a*"
(where [[
takes it literally). That has also to do with how [
can be an external program and receives its argument just normally like every other program (although it can also be a builtin, but then it still has not this special handling).
[[
also has some other nice features, like regular expression matching with =~
along with operators like they are known in C-like languages. Here is a good page about it: What is the difference between test, [
and [[
? and Bash Tests
An issue with double brackets in shell scripting
It sounds like your shell is POSIX sh
, which does not have the [[
builtin. Possible solutions include translating it to an expression that works for sh
or changing the shebang line to be #!/bin/bash
. Changing the shebang is generally the best solution.
You may have a POSIX sh
if you're on Ubuntu, they use dash.
How to use double or single brackets, parentheses, curly braces
In Bash, test
and [
are shell builtins.
The double bracket, which is a shell keyword, enables additional functionality. For example, you can use &&
and ||
instead of -a
and -o
and there's a regular expression matching operator =~
.
Also, in a simple test, double square brackets seem to evaluate quite a lot quicker than single ones.
$ time for ((i=0; i<10000000; i++)); do [[ "$i" = 1000 ]]; done
real 0m24.548s
user 0m24.337s
sys 0m0.036s
$ time for ((i=0; i<10000000; i++)); do [ "$i" = 1000 ]; done
real 0m33.478s
user 0m33.478s
sys 0m0.000s
The braces, in addition to delimiting a variable name are used for parameter expansion so you can do things like:
Truncate the contents of a variable
$ var="abcde"; echo ${var%d*}
abcMake substitutions similar to
sed
$ var="abcde"; echo ${var/de/12}
abc12Use a default value
$ default="hello"; unset var; echo ${var:-$default}
helloand several more
Also, brace expansions create lists of strings which are typically iterated over in loops:
$ echo f{oo,ee,a}d
food feed fad
$ mv error.log{,.OLD}
(error.log is renamed to error.log.OLD because the brace expression
expands to "mv error.log error.log.OLD")
$ for num in {000..2}; do echo "$num"; done
000
001
002
$ echo {00..8..2}
00 02 04 06 08
$ echo {D..T..4}
D H L P T
Note that the leading zero and increment features weren't available before Bash 4.
Thanks to gboffi for reminding me about brace expansions.
Double parentheses are used for arithmetic operations:
((a++))
((meaning = 42))
for ((i=0; i<10; i++))
echo $((a + b + (14 * c)))
and they enable you to omit the dollar signs on integer and array variables and include spaces around operators for readability.
Single brackets are also used for array indices:
array[4]="hello"
element=${array[index]}
Curly brace are required for (most/all?) array references on the right hand side.
ephemient's comment reminded me that parentheses are also used for subshells. And that they are used to create arrays.
array=(1 2 3)
echo ${array[1]}
2
Bash - when using Double Square brackets and when single square brackets
Unlike [[ ]]
, single square brackets are subject to word splitting like normal commands. Think of it similarly as passing arguments to test
builtin. [[ ]]
are special and variables within it are not split with IFS. This is why it's preferable to use [[ ]]
since it's more efficient and safer.
This one is just one of the things you can't do with [
. With [
you'd play around with { }
and ( )
to make it work. Note that ( )
summons a subshell and { }
would always need a semicolon in the end which is ugly. However you can do it safely with [[ ]]
:
[[ a != b && c != d && ( something || something ) ]]
By the way to fix your problem you have to place the variable in double-quotes to prevent splitting:
[ "$STRING" = dog ]
With [[
it's not needed.
Sere Word Splitting: https://www.gnu.org/software/bash/manual/html_node/Word-Splitting.html
Add:
It seems like $STRING
there was actually skipped as an argument for being empty instead of being split. Similarly the concept of it being interpreted as a normal command would apply and applying double quotes would fix it.
Double-bracket if-statement not working
They both "work" for me, however you are using the wrong type of test. The >
inside [[
is doing a textual comparison. For an arithmetic comparison either use the old -gt
or (better) the correct brackets - double parentheses:
if (( nb_dd > 0 )); then
INPUT_TYPE="txt"
fi
Note that the $
is not used, since only numerics can be compared inside ((...))
(using a $
inside might work but can give strange side-effects because of expansion order).
double brackets add -n when use eval
[[
implicitly disables string-splitting, such that an expansion isn't split into multiple arguments.
A single-item test implicitly runs -n
, testing whether that item is the empty string.
Thus, if you want pieces of your condition to be evaluated as separate arguments to [[
, you should have the [[
within the eval
, such that the condition is replaced with the text it contains before [[
's parsing rules are in effect.
eval "[[ $myCondition ]]"
Thus, this would make your code:
myCondition='${queueName} == ${pattern}'
pattern="COMPLETELY_DIFFERENT_PATTERN"
queueName="QM.GCS.SRC.TOTO"
set -x ; eval "[[ $myCondition ]]" && echo CORRECT; set +x
...which emits on stderr the expected log:
+ eval '[[ ${queueName} == ${pattern} ]]'
++ [[ QM.GCS.SRC.TOTO == COMPLETELY_DIFFERENT_PATTERN ]]
+ set +x
Bash double square brackets regex match issue
Assuming you are running Bash 3.2 or newer, the bash manual (scroll down to the description of [[…]]
) states:
Any part of the pattern may be quoted to force the quoted portion to be matched as a string.
And further:
If the pattern is stored in a shell variable, quoting the variable expansion forces the entire pattern to be matched as a string.
Before Bash 3.2, the example you provided would have worked as you expected.
Does not work to execute command in double brackets in bash
The short answer is:
[
and[[
expect an expression.if
expects a command.
Saying:
[[ $(command) ]]
would essentially execute:
[[ -n <command_output> ]]
which may or may not be what you want. On the other hand, saying:
$command && echo something || echo other
would echo something
or other
based on the return code of the command (0
and non-zero respectively).
How does Bash deal with brackets inside of double quoting?
Each command substitution establishes a new quoting context, so the correct way to avoid word splitting inside nested command substitutions is to use double quotes.
In this example, white space is preserved:
$ echo "$(echo "$(echo 'foo bar')")" # outer echo sees 'foo bar'
foo bar
However, missing any of the double quotes means that the string is split by the shell:
$ echo $(echo "$(echo 'foo bar')") # outer echo sees 'foo' 'bar'
foo bar
$ echo "$(echo $(echo 'foo bar'))" # middle echo sees 'foo' 'bar'
foo bar
echo
outputs each argument, separated by a spaces, which is where the single space between "foo" and "bar" comes from.
Related Topics
Number of Executed Instructions Different for Hello World Program Nasm Assembly and C
Unix Standard Directory to Put Custom Executables or Scripts
How to Configure Linux Capabilities Per User
How to Get the Difference (Only Additions) Between Two Files in Linux
Sed with Literal String--Not Input File
Why Child Process Still Alive After Parent Process Was Killed in Linux
Differencebetween -I and -L in Makefile
How Stable Is S3Fs to Mount an Amazon S3 Bucket as a Local Directory
Merge PDF's with PDFtk with Bookmarks
Difference Between Posix Aio and Libaio on Linux
How to Execute Ssh-Keygen Without Prompt
Bash: Inserting a Line in a File at a Specific Location
Why Doesn't Linux Use the Hardware Context Switch via the Tss