What does the following bash syntax mean:
function use_library {
local name=$1
local enabled=1
[[ ,${LIBS_FROM_GIT}, =~ ,${name}, ]] && enabled=0
return $enabled
}
I don't particularly understand the line [[ ,${LIBS_FROM_GIT}, =~ ,${name}, ]]. Is it some kind of regex or string comparison?
This is a trick to compare variables and prevent a weird behaviour if some of them are not defined / are empty.
You can use , or any other. The main thing is that it wants to compare ${LIBS_FROM_GIT} with ${name} and prevent the case when one of them is empty.
As indicated by Etan Reisner in comments, [[ doesn't have empty variable expansion problems. So this trick is usually used when comparing with a single [:
This doesn't work:
$ [ $d == $f ] && echo "yes"
bash: [: a: unary operator expected
But it does if we add a string around both variables:
$ [ ,$d, == ,$f, ] && echo "yes"
$
Finally, note you can use directly this:
[[ ,${LIBS_FROM_GIT}, =~ ,${name}, ]] && return 0 || return 1
Related
This question already has answers here:
How to compare strings in Bash
(12 answers)
Closed 4 years ago.
I'm trying to get an if statement to work in Bash (using Ubuntu):
#!/bin/bash
s1="hi"
s2="hi"
if ["$s1" == "$s2"]
then
echo match
fi
I've tried various forms of the if statement, using [["$s1" == "$s2"]], with and without quotes, using =, == and -eq, but I still get the following error:
[hi: command not found
I've looked at various sites and tutorials and copied those, but it doesn't work - what am I doing wrong?
Eventually, I want to say if $s1 contains $s2, so how can I do that?
I did just work out the spaces bit... :/ How do I say contains?
I tried
if [[ "$s1" == "*$s2*" ]]
but it didn't work.
For string equality comparison, use:
if [[ "$s1" == "$s2" ]]
For string does NOT equal comparison, use:
if [[ "$s1" != "$s2" ]]
For the a contains b, use:
if [[ $s1 == *"$s2"* ]]
(and make sure to add spaces between the symbols):
Bad:
if [["$s1" == "$s2"]]
Good:
if [[ "$s1" == "$s2" ]]
You should be careful to leave a space between the sign of '[' and double quotes where the variable contains this:
if [ "$s1" == "$s2" ]; then
# ^ ^ ^ ^
echo match
fi
The ^s show the blank spaces you need to leave.
You need spaces:
if [ "$s1" == "$s2" ]
I suggest this one:
if [ "$a" = "$b" ]
Notice the white space between the openning/closing brackets and the variables and also the white spaces wrapping the '=' sign.
Also, be careful of your script header. It's not the same thing whether you use
#!/bin/bash
or
#!/bin/sh
Here's the source.
Bash 4+ examples. Note: not using quotes will cause issues when words contain spaces, etc. Always quote in Bash IMO.
Here are some examples Bash 4+:
Example 1, check for 'yes' in string (case insensitive):
if [[ "${str,,}" == *"yes"* ]] ;then
Example 2, check for 'yes' in string (case insensitive):
if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then
Example 3, check for 'yes' in string (case sensitive):
if [[ "${str}" == *"yes"* ]] ;then
Example 4, check for 'yes' in string (case sensitive):
if [[ "${str}" =~ "yes" ]] ;then
Example 5, exact match (case sensitive):
if [[ "${str}" == "yes" ]] ;then
Example 6, exact match (case insensitive):
if [[ "${str,,}" == "yes" ]] ;then
Example 7, exact match:
if [ "$a" = "$b" ] ;then
This question has already great answers, but here it appears that there is a slight confusion between using single equal (=) and double equals (==) in
if [ "$s1" == "$s2" ]
The main difference lies in which scripting language you are using. If you are using Bash then include #!/bin/bash in the starting of the script and save your script as filename.bash. To execute, use bash filename.bash - then you have to use ==.
If you are using sh then use #!/bin/sh and save your script as filename.sh. To execute use sh filename.sh - then you have to use single =. Avoid intermixing them.
I would suggest:
#!/bin/bash
s1="hi"
s2="hi"
if [ $s1 = $s2 ]
then
echo match
fi
Without the double quotes and with only one equals.
$ if [ "$s1" == "$s2" ]; then echo match; fi
match
$ test "s1" = "s2" ;echo match
match
$
I don't have access to a Linux box right now, but [ is actually a program (and a Bash builtin), so I think you have to put a space between [ and the first parameter.
Also note that the string equality operator seems to be a single =.
This is more a clarification than an answer! Yes, the clue is in the error message:
[hi: command not found
which shows you that your "hi" has been concatenated to the "[".
Unlike in more traditional programming languages, in Bash, "[" is a command just like the more obvious "ls", etc. - it's not treated specially just because it's a symbol, hence the "[" and the (substituted) "$s1" which are immediately next to each other in your question, are joined (as is correct for Bash), and it then tries to find a command in that position: [hi - which is unknown to Bash.
In C and some other languages, the "[" would be seen as a different "character class" and would be disjoint from the following "hi".
Hence you require a space after the opening "[".
Use:
#!/bin/bash
s1="hi"
s2="hi"
if [ "x$s1" == "x$s2" ]
then
echo match
fi
Adding an additional string inside makes it more safe.
You could also use another notation for single-line commands:
[ "x$s1" == "x$s2" ] && echo match
For a version with pure Bash and without test, but really ugly, try:
if ( exit "${s1/*$s2*/0}" )2>/dev/null
then
echo match
fi
Explanation: In ( )an extra subshell is opened. It exits with 0 if there was a match, and it tries to exit with $s1 if there was no match which raises an error (ugly). This error is directed to /dev/null.
elif [ "$arg" == "--file" ] || [ "$arg" == "-f" ] && [[ read var ]]
then
touch $var
I'm writing a bash script which takes in a command-line input, either long-form or short-form along with the file name to create an empty file with touch command. the above snippet is what I tried to do, but there's an error unary "read: unary operator expected".please help
This happens for most commands:
$ [[ echo "hello world" ]]
bash: conditional binary operator expected
bash: syntax error near `world"'
This is because [[ .. ]] should be used to compare values, and not to run commands. To run a command, don't wrap it in anything:
$ echo "hello world"
hello world
Applied to your example:
echo "You are expected to type in a value, but you will receive no prompt."
arg="-f"
if [ "$arg" == "--file" ] || [ "$arg" == "-f" ] && read var
then
echo "You entered: $var"
fi
Bash needs to know that it's running a whole command
To make bash aware that it's running a command you can use the backtick syntax (not recommended) or the preferred $() command substitution syntax. Without this syntax, bash is assuming that you're putting two separate strings inside of that condition.
The error you're getting is saying that you are trying to compare two strings without an operator to do so (i.e. -eq or ==).
Here is an example of how to make it recognize your commands:
elif [[ ... ]] && [[ $(read var) ]]
then
However, this won't work. This will evaluate to false. This is because you haven't printed anything out and as such an empty string ("") is falsey.
echo your variable to test its value
elif [[ ... ]] && [[ $(read var; echo $var) ]]
then
This will read into the variable and then test if the user has typed anything into it. If the user doesn't type anything, it will evaluate to false, otherwise, it will evaluate to true and run the body of the elif statement.
This question already has answers here:
How to compare strings in Bash
(12 answers)
Closed 4 years ago.
I'm trying to get an if statement to work in Bash (using Ubuntu):
#!/bin/bash
s1="hi"
s2="hi"
if ["$s1" == "$s2"]
then
echo match
fi
I've tried various forms of the if statement, using [["$s1" == "$s2"]], with and without quotes, using =, == and -eq, but I still get the following error:
[hi: command not found
I've looked at various sites and tutorials and copied those, but it doesn't work - what am I doing wrong?
Eventually, I want to say if $s1 contains $s2, so how can I do that?
I did just work out the spaces bit... :/ How do I say contains?
I tried
if [[ "$s1" == "*$s2*" ]]
but it didn't work.
For string equality comparison, use:
if [[ "$s1" == "$s2" ]]
For string does NOT equal comparison, use:
if [[ "$s1" != "$s2" ]]
For the a contains b, use:
if [[ $s1 == *"$s2"* ]]
(and make sure to add spaces between the symbols):
Bad:
if [["$s1" == "$s2"]]
Good:
if [[ "$s1" == "$s2" ]]
You should be careful to leave a space between the sign of '[' and double quotes where the variable contains this:
if [ "$s1" == "$s2" ]; then
# ^ ^ ^ ^
echo match
fi
The ^s show the blank spaces you need to leave.
You need spaces:
if [ "$s1" == "$s2" ]
I suggest this one:
if [ "$a" = "$b" ]
Notice the white space between the openning/closing brackets and the variables and also the white spaces wrapping the '=' sign.
Also, be careful of your script header. It's not the same thing whether you use
#!/bin/bash
or
#!/bin/sh
Here's the source.
Bash 4+ examples. Note: not using quotes will cause issues when words contain spaces, etc. Always quote in Bash IMO.
Here are some examples Bash 4+:
Example 1, check for 'yes' in string (case insensitive):
if [[ "${str,,}" == *"yes"* ]] ;then
Example 2, check for 'yes' in string (case insensitive):
if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then
Example 3, check for 'yes' in string (case sensitive):
if [[ "${str}" == *"yes"* ]] ;then
Example 4, check for 'yes' in string (case sensitive):
if [[ "${str}" =~ "yes" ]] ;then
Example 5, exact match (case sensitive):
if [[ "${str}" == "yes" ]] ;then
Example 6, exact match (case insensitive):
if [[ "${str,,}" == "yes" ]] ;then
Example 7, exact match:
if [ "$a" = "$b" ] ;then
This question has already great answers, but here it appears that there is a slight confusion between using single equal (=) and double equals (==) in
if [ "$s1" == "$s2" ]
The main difference lies in which scripting language you are using. If you are using Bash then include #!/bin/bash in the starting of the script and save your script as filename.bash. To execute, use bash filename.bash - then you have to use ==.
If you are using sh then use #!/bin/sh and save your script as filename.sh. To execute use sh filename.sh - then you have to use single =. Avoid intermixing them.
I would suggest:
#!/bin/bash
s1="hi"
s2="hi"
if [ $s1 = $s2 ]
then
echo match
fi
Without the double quotes and with only one equals.
$ if [ "$s1" == "$s2" ]; then echo match; fi
match
$ test "s1" = "s2" ;echo match
match
$
I don't have access to a Linux box right now, but [ is actually a program (and a Bash builtin), so I think you have to put a space between [ and the first parameter.
Also note that the string equality operator seems to be a single =.
This is more a clarification than an answer! Yes, the clue is in the error message:
[hi: command not found
which shows you that your "hi" has been concatenated to the "[".
Unlike in more traditional programming languages, in Bash, "[" is a command just like the more obvious "ls", etc. - it's not treated specially just because it's a symbol, hence the "[" and the (substituted) "$s1" which are immediately next to each other in your question, are joined (as is correct for Bash), and it then tries to find a command in that position: [hi - which is unknown to Bash.
In C and some other languages, the "[" would be seen as a different "character class" and would be disjoint from the following "hi".
Hence you require a space after the opening "[".
Use:
#!/bin/bash
s1="hi"
s2="hi"
if [ "x$s1" == "x$s2" ]
then
echo match
fi
Adding an additional string inside makes it more safe.
You could also use another notation for single-line commands:
[ "x$s1" == "x$s2" ] && echo match
For a version with pure Bash and without test, but really ugly, try:
if ( exit "${s1/*$s2*/0}" )2>/dev/null
then
echo match
fi
Explanation: In ( )an extra subshell is opened. It exits with 0 if there was a match, and it tries to exit with $s1 if there was no match which raises an error (ugly). This error is directed to /dev/null.
I'm under bash and tried to match a short string with a pattern:
$[[ "ab" =~ "^a*" ]]
$echo $?
0
OK, as I expected, but then I changed into "^b*", I expect this time, it doesn't match:
$[[ "ab" =~ "^b*" ]]
$echo $?
0
Strangely the return value is still "OK". Why is that, where did I get wrong?
Thanks.
Regex ^b* means 0 or more b at the start so obviously it will return true for any input.
You should use + quantifier for 1 or more matches and avoid quoting regex in bash as this:
[[ "ab" =~ ^a+ ]] && echo 'ok' || echo 'no'
ok
[[ "ab" =~ ^b+ ]] && echo 'ok' || echo 'no'
no
Likewise you can use ^a or ^a.* as well.
In addition to anubhava's correct answer, and because bash's regex are particulary expensive, I would say:
If your need is to check for presence of a character at 1st position of a string, and because this kind of test have to be done against variables:
myVar="ab"
[ "$myVar" ] && [ -z "${myVar%%a*}" ] && echo "String '$myVar' begin with 'a'"
will output: String 'ab' begin with 'a', but
myVar="ab"
[ "$myVar" ] && [ -z "${myVar%%b*}" ] && echo "String '$myVar' begin with 'b'"
won't produce anything!
See also: String contains in Bash
I cannot find the difference between:
[ $foo = b* ]
[ $foo == b* ]
[[ $foo = b* ]]
[[ $foo == b* ]]
[] vs [[ ]] in general was covered at Is [[ ]] preferable over [ ] in bash scripts? so let's not touch it.
= vs ==:
Inside [ ]
= is POSIX and checks if strings are equal
== is a Bash defined alias to it, see man bash.
So only use = as it is both more portable and shorter.
Inside [[ ]]
[[ ]] is not POSIX, so we refer only to man bash.
It says under CONDITIONAL EXPRESSIONS that = and == are the same inside [[ ]] and that both do pattern matching as described at "Compound Commands".
Then "Compound Commands" is the same pattern used for glob expansion, e.g.:
[[ 'abcde' = ?b[cC]* ]] && echo true
possibly with extglob extensions.
Note that you must not quote the pattern: it will not glob expand to files as usual. If you quote it, you lose the pattern matching magic and get literal characters.
Difference between [] and [[]] check this
Difference between = and ==
= is assignment operator
== equality check operator OR conditional operator