Shell script to check if a string contains something - shell

I have the following shell script.
if [ "$group" == "First*" ]]
then
OWNER_EMAIL=first-logs#ginger.com
elif [ "$group" == "Second*" ]]
then
OWNER_EMAIL=second-team#ginger.com
fi
It does not throw any error , but does not execute the if statement properly if $group contains a First or a Second inside. Can any one tell me where I am going wrong.

You can also consider a case statement for efficiency:
case "$group" in
First*)
OWNER_EMAIL=first-logs#ginger.com
;;
Second*)
OWNER_EMAIL=second-team#ginger.com
;;
esac
You can add *) ... ;; as well for default action.

Remove the quotes "" and it is done
if [ "$group" == First* ]
then
OWNER_EMAIL=first-logs#ginger.com
elif [ "$group" == Second* ]
then
OWNER_EMAIL=second-team#ginger.com
fi

When we use double quotes the wildcard character are not retained ... the check condition is looking for a exact "First*" and "Second*" match .
change your code in following way
if [[ "$group" == First* ]]
then
OWNER_EMAIL=first-logs#ginger.com
elif [[ "$group" == Second* ]]
then
OWNER_EMAIL=second-team#ginger.com
fi

Related

This script is supposed to run every 12 hours but outputs a "Command 200 not found" error on each test. Any ideas? [duplicate]

How do I compare a variable to a string (and do something if they match)?
Using variables in if statements
if [ "$x" = "valid" ]; then
echo "x has the value 'valid'"
fi
If you want to do something when they don't match, replace = with !=. You can read more about string operations and arithmetic operations in their respective documentation.
Why do we use quotes around $x?
You want the quotes around $x, because if it is empty, your Bash script encounters a syntax error as seen below:
if [ = "valid" ]; then
Non-standard use of == operator
Note that Bash allows == to be used for equality with [, but this is not standard.
Use either the first case wherein the quotes around $x are optional:
if [[ "$x" == "valid" ]]; then
or use the second case:
if [ "$x" = "valid" ]; then
Or, if you don't need an else clause:
[ "$x" == "valid" ] && echo "x has the value 'valid'"
a="abc"
b="def"
# Equality Comparison
if [ "$a" == "$b" ]; then
echo "Strings match"
else
echo "Strings don't match"
fi
# Lexicographic (greater than, less than) comparison.
if [ "$a" \< "$b" ]; then
echo "$a is lexicographically smaller then $b"
elif [ "$a" \> "$b" ]; then
echo "$b is lexicographically smaller than $a"
else
echo "Strings are equal"
fi
Notes:
Spaces between if and [ and ] are important
> and < are redirection operators so escape it with \> and \< respectively for strings.
To compare strings with wildcards, use:
if [[ "$stringA" == *"$stringB"* ]]; then
# Do something here
else
# Do something here
fi
I have to disagree one of the comments in one point:
[ "$x" == "valid" ] && echo "valid" || echo "invalid"
No, that is not a crazy oneliner
It's just it looks like one to, hmm, the uninitiated...
It uses common patterns as a language, in a way;
And after you learned the language.
Actually, it's nice to read
It is a simple logical expression, with one special part: lazy evaluation of the logic operators.
[ "$x" == "valid" ] && echo "valid" || echo "invalid"
Each part is a logical expression; the first may be true or false, the other two are always true.
(
[ "$x" == "valid" ]
&&
echo "valid"
)
||
echo "invalid"
Now, when it is evaluated, the first is checked. If it is false, than the second operand of the logic and && after it is not relevant. The first is not true, so it can not be the first and the second be true, anyway.
Now, in this case is the the first side of the logic or || false, but it could be true if the other side - the third part - is true.
So the third part will be evaluated - mainly writing the message as a side effect. (It has the result 0 for true, which we do not use here)
The other cases are similar, but simpler - and - I promise! are - can be - easy to read!
(I don't have one, but I think being a UNIX veteran with grey beard helps a lot with this.)
The following script reads from a file named "testonthis" line by line and then compares each line with a simple string, a string with special characters and a regular expression. If it doesn't match, then the script will print the line, otherwise not.
Space in Bash is so much important. So the following will work:
[ "$LINE" != "table_name" ]
But the following won't:
["$LINE" != "table_name"]
So please use as is:
cat testonthis | while read LINE
do
if [ "$LINE" != "table_name" ] && [ "$LINE" != "--------------------------------" ] && [[ "$LINE" =~ [^[:space:]] ]] && [[ "$LINE" != SQL* ]]; then
echo $LINE
fi
done
You can also use use case/esac:
case "$string" in
"$pattern" ) echo "found";;
esac
Bash 4+ examples. Note: not using quotes will cause issues when words contain spaces, etc. Always quote in Bash, IMO.
Here are some examples in 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
Enjoy.
I would probably use regexp matches if the input has only a few valid entries. E.g. only the "start" and "stop" are valid actions.
if [[ "${ACTION,,}" =~ ^(start|stop)$ ]]; then
echo "valid action"
fi
Note that I lowercase the variable $ACTION by using the double comma's. Also note that this won't work on too aged bash versions out there.
I did it in this way that is compatible with Bash and Dash (sh):
testOutput="my test"
pattern="my"
case $testOutput in (*"$pattern"*)
echo "if there is a match"
exit 1
;;
(*)
! echo there is no coincidence!
;;esac
I was struggling with the same situation for a while, here is how I could resolve:
if [ "$var1" == "$var2" ]; then
#dowhateveryouwant
fi
Be careful with the spaces left before and after the comparison sign, otherwise it won't work or it'll give you an unexpected result.
I've spent so much time on using a single equal(=) sign but didn't work. I Hope it can help.
Are you having comparison problems? (like below?)
var="true"
if [[ $var == "true" ]]; then
# It should be working, but it is not...
else
# It is falling here...
fi
Try like the =~ operator (regular expression operator) and it might work:
var="true"
if [[ $var =~ "true" ]];then
# Now it works here!!
else
# No more inequality
fi
Bash regex operator =~ (official reference)
StackOverflow further examples (here)

Running bash script throws syntax error: operand expected [duplicate]

How do I compare a variable to a string (and do something if they match)?
Using variables in if statements
if [ "$x" = "valid" ]; then
echo "x has the value 'valid'"
fi
If you want to do something when they don't match, replace = with !=. You can read more about string operations and arithmetic operations in their respective documentation.
Why do we use quotes around $x?
You want the quotes around $x, because if it is empty, your Bash script encounters a syntax error as seen below:
if [ = "valid" ]; then
Non-standard use of == operator
Note that Bash allows == to be used for equality with [, but this is not standard.
Use either the first case wherein the quotes around $x are optional:
if [[ "$x" == "valid" ]]; then
or use the second case:
if [ "$x" = "valid" ]; then
Or, if you don't need an else clause:
[ "$x" == "valid" ] && echo "x has the value 'valid'"
a="abc"
b="def"
# Equality Comparison
if [ "$a" == "$b" ]; then
echo "Strings match"
else
echo "Strings don't match"
fi
# Lexicographic (greater than, less than) comparison.
if [ "$a" \< "$b" ]; then
echo "$a is lexicographically smaller then $b"
elif [ "$a" \> "$b" ]; then
echo "$b is lexicographically smaller than $a"
else
echo "Strings are equal"
fi
Notes:
Spaces between if and [ and ] are important
> and < are redirection operators so escape it with \> and \< respectively for strings.
To compare strings with wildcards, use:
if [[ "$stringA" == *"$stringB"* ]]; then
# Do something here
else
# Do something here
fi
I have to disagree one of the comments in one point:
[ "$x" == "valid" ] && echo "valid" || echo "invalid"
No, that is not a crazy oneliner
It's just it looks like one to, hmm, the uninitiated...
It uses common patterns as a language, in a way;
And after you learned the language.
Actually, it's nice to read
It is a simple logical expression, with one special part: lazy evaluation of the logic operators.
[ "$x" == "valid" ] && echo "valid" || echo "invalid"
Each part is a logical expression; the first may be true or false, the other two are always true.
(
[ "$x" == "valid" ]
&&
echo "valid"
)
||
echo "invalid"
Now, when it is evaluated, the first is checked. If it is false, than the second operand of the logic and && after it is not relevant. The first is not true, so it can not be the first and the second be true, anyway.
Now, in this case is the the first side of the logic or || false, but it could be true if the other side - the third part - is true.
So the third part will be evaluated - mainly writing the message as a side effect. (It has the result 0 for true, which we do not use here)
The other cases are similar, but simpler - and - I promise! are - can be - easy to read!
(I don't have one, but I think being a UNIX veteran with grey beard helps a lot with this.)
The following script reads from a file named "testonthis" line by line and then compares each line with a simple string, a string with special characters and a regular expression. If it doesn't match, then the script will print the line, otherwise not.
Space in Bash is so much important. So the following will work:
[ "$LINE" != "table_name" ]
But the following won't:
["$LINE" != "table_name"]
So please use as is:
cat testonthis | while read LINE
do
if [ "$LINE" != "table_name" ] && [ "$LINE" != "--------------------------------" ] && [[ "$LINE" =~ [^[:space:]] ]] && [[ "$LINE" != SQL* ]]; then
echo $LINE
fi
done
You can also use use case/esac:
case "$string" in
"$pattern" ) echo "found";;
esac
Bash 4+ examples. Note: not using quotes will cause issues when words contain spaces, etc. Always quote in Bash, IMO.
Here are some examples in 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
Enjoy.
I would probably use regexp matches if the input has only a few valid entries. E.g. only the "start" and "stop" are valid actions.
if [[ "${ACTION,,}" =~ ^(start|stop)$ ]]; then
echo "valid action"
fi
Note that I lowercase the variable $ACTION by using the double comma's. Also note that this won't work on too aged bash versions out there.
I did it in this way that is compatible with Bash and Dash (sh):
testOutput="my test"
pattern="my"
case $testOutput in (*"$pattern"*)
echo "if there is a match"
exit 1
;;
(*)
! echo there is no coincidence!
;;esac
I was struggling with the same situation for a while, here is how I could resolve:
if [ "$var1" == "$var2" ]; then
#dowhateveryouwant
fi
Be careful with the spaces left before and after the comparison sign, otherwise it won't work or it'll give you an unexpected result.
I've spent so much time on using a single equal(=) sign but didn't work. I Hope it can help.
Are you having comparison problems? (like below?)
var="true"
if [[ $var == "true" ]]; then
# It should be working, but it is not...
else
# It is falling here...
fi
Try like the =~ operator (regular expression operator) and it might work:
var="true"
if [[ $var =~ "true" ]];then
# Now it works here!!
else
# No more inequality
fi
Bash regex operator =~ (official reference)
StackOverflow further examples (here)

Why doesn't my comparison in BASH work?

I am trying to compare some characters in BASH
read a
if (($a == "Y"))
then
echo "YES"
elif (($a == "y"))
then
echo "YES"
else
echo "NO"
fi
but for some reason it does not work as expected. It always output YES. Looking at this super simple script, I can not understand what is wrong.
It's due to spacing and the brackets.
read a
if [[ $a == "Y" ]]
then
echo "YES"
elif [[ $a == "y" ]]
then
echo "YES"
else
echo "NO"
fi
You should review bash comparison. You're trying to use an arithmetic expansion construct to do string comparison. Instead, you should use the [ exp ] or [[ exp ]] constructs.
((expression)) is used for 'arithmetic evaluation' and strings inside (( )) will be treated as variable names, thus
if (($a == "Y"))
is equivalent to
if [ $a == $Y ]
(if $Y is a string, then bash will try to expand the name until it finds a numeric value or undefined variable)
You need to use [ ] or [[ ]] to compare strings as #KRUKUSA said.

case or If string contains word1 and word2

In this example I want it to know if $# contains two words/symbols "load" and "/"
for one word/symbol this works
case "$#" in */*)
;;
echo "going to do stuff"
*)
echo "will do something else"
;;
esac
or
string='My string';
if [[ "$string" == *My* ]]
then
echo "It's there!";
fi
But if two words/symbols appear at random places I cant figure out how to do it.
Update:
The input will the module command. In this case I want to know if it is the module load with or without / that indicate version. the command will look like this
1) module load appname/1.1.1 or
2) module load appname
3) module (not load) (list, avail etc)
It is number 1 I am interested in for now.
3 will in some cases be variation of 1.
2 will be run as is but will include a message to the user
The slow way would be to iterate through the array twice and then check if both "load" and "/" were present, like this:
for element in $#; do [[ "$element" == "load" ]] && loadPresent=1; done
for element in $#; do [[ "$element" =~ ".*/.*" ]] && slashPresent=1; done
if [[ $loadPresent == 1 ]] && [[ $slashPresent == 1 ]]; then
echo "Contains load and /"
fi
(As I interpreted your question you want one parameter to be exactly "load" and another one to contain a slash.)
Something like this is possible:
if [[ ${#} =~ .*/.* && ${#} =~ ((^)|([ ]))load(($)|([ ])) ]]
then
echo both
fi
-or-
if LOAD=0 && SLASH=0 && \
for ARG in ${#};
do
if [ "${ARG#*/}" != "${ARG}" ]; then SLASH=1; fi
if [ "${ARG}" = "load" ]; then LOAD=1; fi
done && [ "${LOAD}${SLASH}" = "11" ];
then
echo both
fi
-or-
function loadslash()
{
LOAD=0 && SLASH=0
for ARG in ${#};
do
if [ "${ARG#*/}" != "${ARG}" ]; then SLASH=1; fi
if [ "${ARG}" = "load" ]; then LOAD=1; fi
done
test "${LOAD}${SLASH}" = "11"
}
if loadslash ${#}
then
echo both
fi
this will satisfy your requirements
if [[ $1 == "load" ]]; then
if [[ $2 == */* ]]; then
do first case
else
do second case
fi
else
do third case
fi

if arguments is equal to this string, define a variable like this string

I am doing some bash script and now I got one variable call source and one array called samples, like this:
source='country'
samples=(US Canada Mexico...)
as I want to expand the number of sources (and each source has its own samples) I tried to add some arguments to do this. I tried this:
source=""
samples=("")
if [ $1="country" ]; then
source="country"
samples="US Canada Mexico..."
else
echo "try again"
fi
but when I ran my script source countries.sh country it didn't work.
What am I doing wrong?
Don't forget about spaces:
source=""
samples=("")
if [ $1 = "country" ]; then
source="country"
samples="US Canada Mexico..."
else
echo "try again"
fi
You can use either "=" or "==" operators for string comparison in bash. The important factor is the spacing within the brackets. The proper method is for brackets to contain spacing within, and operators to contain spacing around. In some instances different combinations work; however, the following is intended to be a universal example.
if [ "$1" == "something" ]; then ## GOOD
if [ "$1" = "something" ]; then ## GOOD
if [ "$1"="something" ]; then ## BAD (operator spacing)
if ["$1" == "something"]; then ## BAD (bracket spacing)
Also, note double brackets are handled slightly differently compared to single brackets ...
if [[ $a == z* ]]; then # True if $a starts with a "z" (pattern matching).
if [[ $a == "z*" ]]; then # True if $a is equal to z* (literal matching).
if [ $a == z* ]; then # File globbing and word splitting take place.
if [ "$a" == "z*" ]; then # True if $a is equal to z* (literal matching).
It seems that you are looking to parse commandline arguments into your bash script. I have searched for this recently myself. I came across the following which I think will assist you in parsing the arguments:
http://rsalveti.wordpress.com/2007/04/03/bash-parsing-arguments-with-getopts/
I added the snippet below as a tl;dr
#using : after a switch variable means it requires some input (ie, t: requires something after t to validate while h requires nothing.
while getopts “ht:r:p:v” OPTION
do
case $OPTION in
h)
usage
exit 1
;;
t)
TEST=$OPTARG
;;
r)
SERVER=$OPTARG
;;
p)
PASSWD=$OPTARG
;;
v)
VERBOSE=1
;;
?)
usage
exit
;;
esac
done
if [[ -z $TEST ]] || [[ -z $SERVER ]] || [[ -z $PASSWD ]]
then
usage
exit 1
fi
./script.sh -t test -r server -p password -v

Resources