How to assign a variable inside if condition in shell script - bash

I would like to know how to assign a variable inside if block in shell script..
Below is my code..
if [[ -z "$MMBOX_PATH" || -z "$BACKUP_PATH" || -z "$REMOTE_SERVER" || -z "$LOG_PATH" ]]
then
echo -e "Must Provide All Required Paths [$FLAG is Empty].."
exit 1
fi
The above code will run whenever it found empty variable, but I also wants to know which variable is empty (E.g., In above code suppose if LOG_PATH variable is empty then it should display in echo output in place of $FLAG )
I tried following codes..
if [[ `FLAG='MMBOX_PATH'` && -z "$MMBOX_PATH" || `FLAG='BACKUP_PATH'` && -z "$BACKUP_PATH" || `FLAG='REMOTE_SERVER'` && -z "$REMOTE_SERVER" || `FLAG='LOG_PATH'` && -z "$LOG_PATH" ]]
then
echo -e "Must Provide All Required Paths [$FLAG is Empty].."
exit 1
fi
But above code returns false hence it is not printing the content inside echo.
I also tried to keep FLAG variable before condition execution, but every time it returns 'Nothing'
if FLAG='MMBOX_PATH' && [[ -z "$MMBOX_PATH" ]]
then
echo -e "Must Provide All Required Paths [$FLAG is Empty].."
exit 1
fi
In above case I'm getting FLAG='MMBOX_PATH' in output but if I add one more condition to that if nothing is printing (Means if I check same thing for BACKUP_PATH,REMOTE_SERVER..)
if FLAG='MMBOX_PATH' && [[ -z "$MMBOX_PATH" ]] && FLAG='LOG_PATH' && [[ -z "$LOG_PATH" ]]
then
echo -e "Must Provide All Required Paths [$FLAG is Empty].."
exit 1
fi
In this case nothing is printing even though MMBOX_PATH present and LOG_PATH empty.
Note: Using if condition each and every variable it is possible to know which variable is empty,but I don't want to extend my lines with if-else conditions I just want to know in that if block itself how to assign a variable and prints once condition is true.
Can anybody help me how to get empty variable..? (/bin/bash)

If all you are doing is checking existence with the if you could use a function.
check() {
for i in "$#";do
if [[ -z "${!i}" ]]
then
echo -e "Must Provide All Required Paths [\$$i is Empty].."
exit 1
fi
done
}
check MMBOX_PATH BACKUP_PATH REMOTE_SERVER LOG_PATH

Shell already provides a syntax for verifying that a variable has a value and exits if it does not:
: ${MMBOX_PATH:?Must provide MMBOX_PATH}
: ${BACKUP_PATH:?Must provide BACKUP_PATH}
: ${REMOTE_SERVER:?Must provide REMOVE_SERVER}
: ${LOG_PATH:?Must provide LOG_PATH}
There's no need to define a check function that does the same thing.
The initial colon is the do-nothing command; the shell evaluates its arguments, and : exits with status 0 immediately. The parameter expansion is what verifies that the named parameter has a value. If it does not, the given error message is printed. If the shell is not interactive, it also exits with status 1.

Related

Why my if/else statement doesn't work? (shell)

I have problem with this shell script:
current_time=$(date +"%T");
current_day_of_week="$(date +'%u')";
if [[ current_day_of_week == 1 ]];
then echo "Setting max time to 03:00:00" && max_time="03:00:00";
else echo "Setting max time to 01:30:00" && max_time="01:30:00"; fi;
I want to set variable max_time to 03:00:00 when it's monday, but the code doesn't work :(
The string "current_day_of_week" is not the same as the string "1". If you want to compare the value of the variable, you need to dereference it. Replace
if [[ current_day_of_week == 1 ]];
with
if [ "$current_day_of_week" = 1 ];
Since you're not getting a syntax error, we can assume you are using a shell that supports the [[ syntax (you should probably change the tag !) so you can use:
if [[ $current_day_of_week == 1 ]];
Note that although quoting variables is not strictly necessary inside the [[ construct, it is a good idea to use quotes anyway:
if [[ "$current_day_of_week" == 1 ]];

Redundant use of :- in Bash?

I have this code inside a function:
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
What is the role of :- here? Isn't it redundant? To be specific, could we not write the if statement this way?
if [ "${!var}" ] && [ "${!fileVar}" ]; then
How does it help to have an empty "word" on the right side of :-?
Figured it out. The :- construct in indirect parameter expansion prevents the script from failing when run with set -u.
Here is an example:
set -u
var=x
[[ ${!var:-} ]] && echo This works
[[ ${!var} ]] && echo This should fail
echo "This should print only when run without 'set -u'"
which gives this output:
line 6: !var: unbound variable
If the same statements are run without set -u, we get:
This should print only when run without 'set -u'
However, this trick wouldn't work in case we are using direct parameter expansion. So,
set -u
[[ ${var:-} ]] && echo Does this work
still throws the error:
tt.sh: line 6: var: unbound variable

Prevent hardcoding of if condition in bash

Following is my sample code which is setting environment settings to the session. I am getting env setting name as first argument of the function and storing it to supplied_env , I have a list of possible environments which contains possible or allowed environments allowed for this script. I have to keep this list hard coded which is acceptable. However in the end just before sourcing the environment file, I have to run if condition with hardcoded environment name(env1 or env2). Is there any way to only keep the environment names hardcoded only at the beginning and match them dynamically later ?
#!/bin/bash
supplied_env="${1}"
possible_env="env1 env2"
if [ $# -ne 1 ];then
echo "You must provide any one of these values ${possible_env}"
exit 1;
elif ! echo "${possible_env}"|grep "$supplied_env" ;then
echo "Incorrect value provided, You must provide any one of these values ${possible_env}"
exit 2;
else
target_env=${supplied_env}
fi
if [ ${supplied_env} == "env1" ];then #<------How to avoid using `env1` string here, rather get it from possible_env ?
source ~/.env1
elif [ ${supplied_env} == "env2" ];then
source ~/.env2
else
echo "Error..."
fi
In short, in future there would be move environments like env3 ,env4 etc. I just want to update the script at one place not at multiple places.
if [ ${supplied_env} == "env1" ];then #<------How to avoid using `env1` string here, rather get it from possible_env ?
source ~/.env1
elif [ ${supplied_env} == "env2" ];then
source ~/.env2
else
echo "Error..."
fi
You can substitute $supplied_env in the source statement. Since you've already done error checking you don't need any other logic, just a single source call.
source ~/."$supplied_env"
Store the allowed names as keys in an associative array.
declare -A possible_env=([env1]=~/.env1 [env2]=~/.env2)
Then you can check for the existence of a key in this array.
supplied_env="${1:?Must supply an environment name}"
declare -A possible_env=([env1]=~/.env1 [env2]=~/.env2)
if [[ ! -v possible_env[$suppliedEnv] ]]; then
echo "Incorrect value provided, You must provide any one of these values: ${!possible_env[*]}"
exit 2;
fi
source "${possible_env[$suppliedEnv]"

Finding a part of a string in another string variable in bash

I have an issue in finding a part of string variable in another string variable, I tried many methods but none worked out..
for example:
echo -e " > Required_keyword: $required_keyword"
send_func GUI WhereAmI
echo -e " > FUNCVALUE: $FUNCVALUE"
flag=`echo $FUNCVALUE|awk '{print match($0,"$required_keyword")}'`;
if [ $flag -gt 0 ];then
echo "Success";
else
echo "fail";
fi
But it always gives fail though there are certain words in variable which matches like
0_Menu/BAA_Record ($required_keyword output string)
Trying to connect to 169.254.98.226 ... OK! Executing sendFunc GUI
WhereAmI Sent Function WhereAmI [OK PageName:
"_0_Menu__47__BAA_Record" ($FUNCVALUE output string)
As we can see here the BAA_Record is common in both of the output still, it always give FAIL
The output echo is
> Required_keyword: 0_Menu/BAA_Record
> FUNCVALUE:
Trying to connect to 169.254.98.226 ... OK!
Executing sendFunc GUI WhereAmI
Sent Function WhereAmI [OK]
PageName: "_0_Menu__47__BAA_Record"
Bash can do wildcard and regex matches inside double square brackets.
if [[ foobar == *oba* ]] # wildcard
if [[ foobar =~ fo*b.r ]] # regex
In your example:
if [[ $FUNCVALUE = *$required_keyword* ]]
if [[ $FUNCVALUE =~ .*$required_keyword.* ]]
Not sure if I understand what you want, but if you need to find out if there's part of string "a" present in variable "b" you can use simply just grep.
grep -q "a" <<< "$b"
[[ "$?" -eq 0 ]] && echo "Found" || echo "Not found"
EDIT: To clarify, grep searches for string a in variable b and returns exit status (see man grep, hence the -q switch). After that you can check for exit status and do whatever you want (either with my example or with regular if statement).

Testing empty variables

I have a large number of variables in my script, and I want the script to error out if any one of the variables are empty.
I know I can:
if [[ -z "$var_1" ]] || [[ -z "$var_2" ]] || ... [[ -z "$var_n" ]]; then
# failure message
fi
However, I cannot inform the user which variable was empty if I do it in this way. Is there an alternative approach to the above so that I can inform the user about the empty variable?
#!/bin/sh
foo=(var_1 var_2 var_n)
for bar in ${foo[*]}
do
if [[ ! ${!bar} ]]
then
echo $bar is empty
fi
done
Just use ${var:?var is empty or unset} the first time you reference the variable. If empty strings are acceptable and you only care if the variables are set, do ${var?var is unset}. Using ? in the parameter expansion causes the shell to terminate and if the variable is (empty or) unset.

Resources