Test if string is "*" - string

For some reason I just cannot get an if statement to test if a string is literally equal to an asterisk. I have tried every combination I can think of and I don't want to mess with file globbing. Please help.
if [ $VAR = "\*" ]; then
* UPDATE *
Both of those suggestions work. The issue is apparently not with the * comparison, but with the other part of the if statement. This is supposed to compare whether or not $VAR is between 0 and 20 or is a wildcard.
if [ "$VAR" -gt 0 ] && [ "$VAR" -lt 20 ] || [ "$VAR" = "*" ]; then
This other part of the IF statement if apparently goofing up the last comparison.
* UPDATE *
Just tested it again and checked my syntax. When $VAR is between 0 and 20 it works great (true), when $VAR is over 20 it also works (reports false), however as soon as I try to set $VAR to an * the if statement freaks and pops out:
line 340: [: *: integer expression expected

Another version using bash's double brackets:
if [[ $VAR = "*" || ($VAR -gt 0 && $VAR -lt 20) ]]; then
The double brackets allow you to use && and ||. Also, bash doesn't perform word splitting or glob expansion on arguments to [[, so $VAR doesn't need to be quoted and ( doesn't need to be escaped.
[[ also works in zsh and ksh, if you need (some) portability.

$ VAR="*"
$ if [ "$VAR" = "*" ] ; then echo Star ; fi
Star
Quote variables when they could contain glob patterns, whitespace or other interpretable sequences you don't want interpreted. This also avoids syntax errors if $VAR is empty.
For your second problem, [ "$VAR" -gt 0 ] doesn't make sense if $VAR is anything but a number. So you must avoid having that test evaluated in that case. Simply exchange your tests - || and && are short-circuiting (in bash at least, not sure if that's POSIX):
if [ "$VAR" = "*" ] || [ "$VAR" -gt 0 -a "$VAR" -lt 20 ] ; then

Related

Command output to string comparison in Zsh [duplicate]

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.

How to check if package is installed, then ask if user wants to install package? [duplicate]

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.

Bash: Why does my If-Statement always evaluate to true?

I'm trying to write what would seem to be a simple if statement in most languages, however in bash this doesnt seem to work at all.
When I run the script it always enters the first if statement. Can anyone offer help me as to what I am doing wrong?
PERC=.5
if [ "$PERC" > "1.00" ]
then
echo "Entered first statement"
else
if [ "$PERC" < "1.00" ]
then
echo "Entered second statement"
fi
fi
Thanks for your help.
> and < compare strings, not numbers (and must be backslashed or quoted in single [...]). Use -gt, -lt etc. to compare numbers, or use arithmetic conditions:
if (( a < b || b <= c )) ; then
Note, however, that bash only handles integer arithmetics. To compare floats, you can use bc:
if [[ 1 == $( bc <<< '1.5 < 1.00' ) ]] ; then
> and < are the I/O redirection operators. So
if [ "$PERC" > "1.0" ]
is executing the command [ "$PERC ], redirecting the output to the file 1.0, and then if is testing whether the command succeeded. [ "$PERC" ] simply tests whether "$PERC" is a non-empty string.
To use them as operators in the test command, you need to quote or escape them:
if [ "$PERC" '>' "1.0" ]
You could also use bash's [[ conditional syntax instead of the [ command:
if [[ $PERC > "1.0" ]]

Unexpected output in bash shell script

For the below script I am expecting the output to be msg_y and msg_z. But it is printing msg_x and msg_z. Can somebody explain to me what is going on?
#!/bin/bash
set -x
vr=2
echo $vr
if [ $vr > 5 ]
then
echo "entered 1st if"
echo "msg_x"
echo "out of 1st if"
if [ $vr < 8 ]; then
echo "in of 2nd if"
echo "msg_y"
else
echo "msg_z"
fi
else
if [ $vr > 1 ]; then echo "msg_y"
else echo "msg_z"
fi
fi
This expression
[ $vr > 5 ]
is being parsed as an output redirection; check to see if you have a file named "5" now. The output redirection is vacuously true. Note that the usual admonition to quote parameters inside a test expression would not help here (but it's still a good idea).
You can escape the > so that it is seen as an operator in the test command:
if [ "$vr" \> 5 ]; then
or you can use the integer comparison operator -gt
if [ "$vr" -gt 5 ]; then.
Since you are using bash, you can use the more robust
conditional expression
if [[ $vr > 5 ]]; then
or
if [[ $vr -gt 5 ]]; then
or use an arithmetic expression
if (( vr > 5 )); then
to do your comparisions (likewise for the others).
Note: although I showed how to make > work as a comparison operator even when surrounded by integers, don't do this. Most of the time, you won't get the results you want, since the arguments are compared lexicographically, not numerically. Try [ 2 \> 10 ] && echo What? Either use the correct integer comparison operators (-gt et al.) or use an arithmetic expression.

How do I play with test command properly?

[root#jiaoyou ~]# test 1 = 1 -a 0 = 1
[root#jiaoyou ~]# if [1 = 1 -a 0 = 1]then echo 1;else echo 2;fi
-bash: syntax error near unexpected token `else'
Why test doesn't give any output and the if statement fails?
Can someone point out what's wrong here?
UPDATE
Can someone illustrate how to simulate complex expressions like 1=1 and (0=1 or 1=1) with [[?
Return codes are not printed; you must echo the value of $? in order to see it.
[ is a command. Just as you don't write echoHelloworld, you can't write [1 ....
There are several equivalent ways of doing the test you're looking for. First, essentially the way you're doing it, but with the syntax fixed (added required spaces around the parameters to the [ (aka test) command, and a ; between ] and then):
if [ 1 = 1 -a 0 = 1 ];then echo 1;else echo 2;fi
Here's a version with explicit grouping in the expression; note that the parentheses have to be escaped because they're special characters in the shell, but in this case we want them passed to the [ command as arguments:
if [ \( 1 = 1 \) -a \( 0 = 1 \) ];then echo 1;else echo 2;fi
Another version with explicit grouping, this time using two separate [ commands connected with bash's && operator (note that this can also connect other commands):
if [ 1 = 1 ] && [ 0 = 1 ];then echo 1;else echo 2;fi
And finally, a couple of examples using bash's [[ operator instead of the [ command; note that [[ isn't a command, so its expression isn't parsed as command arguments, allowing it a more intuitive syntax (e.g. allowing && and || as operators, and parentheses and !<> comparisons without escaping):
if [[ 1 = 1 && 0 = 1 ]];then echo 1;else echo 2;fi
if [[ ( 1 = 1 ) && ( 0 = 1 ) ]];then echo 1;else echo 2;fi
Some more notes/warnings: the = operator being used in all of these examples does string comparisons rather than numeric comparison (i.e. [ 1 = 01 ] is false); if you want numeric comparison use -eq instead (similarly, < and > are string comparisons, while -lt and -gt are numeric). Also, if you're comparing strings that include spaces, '[' can mistake the string for part of the expression under some circumstances (esp. if you don't have the strings wrapped in double-quotes); as far as I know [[ never has this problem. Overall, if you're using shells that support [[, it's much easier to deal with than [.
As #IgnacioVazquez-Abrams correctly states, test just sets the error code.
That said, here's a nice bash-ism for quickly checking the error value:
test [ expr ] && echo SUCCESS || echo FAIL
Due to how && and || short circuit, that will output SUCCESS or FAIL depending on whether test returns 0 or non-0.

Resources