Logical OR evaluates all expression in Bash script - bash

Consider this simple shell script:
#!/bin/bash
exp1="[ $1 -gt 5 ]";
exp2="[ `ping localhost -c 4 | wc -l` -gt 0 ]";
if eval $exp1 || eval $exp2
then
echo Ok!
fi
I was expecting that passing 10 to this script, the ping was not executed, but it is clearly executed (since the script takes some seconds to write "Ok!").
I was wondering if there is a way to avoid/optimize this behavior?

It will execute ping because you have:
exp2="[ `ping localhost -c 4 | wc -l` -gt 0 ]";
which uses command substitution before evaluating the condition due to double quotes.
Use single quotes to delay the execution until the eval line, like so:
#!/bin/bash
exp1='[[ $1 -gt 5 ]]'
exp2='[[ $(ping localhost -c 4 | wc -l) -gt 0 ]]'
if eval $exp1 || eval $exp2
then
echo Ok!
fi
Better yet, use functions. Don't store commands in variables!
exp1() { [[ $1 -gt 5 ]]; }
exp2() { [[ $(ping localhost -c 4 | wc -l) -gt 0 ]]; }
if exp1 "$1" || exp2
then
echo Ok!
fi

Related

error script_name.sh: line 13: [[0: command not found

Good morning ! trying to execute this code but i have an error on if statement .
error message : error script_name.sh: line 6: [[0: command not found
the problèm is on "if" statement.
help please
#!/bin/ksh
jour=$(date +%Y%m%d)
#Control if run is ok or not before sending mail
dir_resultFailure=/transfertCLINK/Share/RESULT_UAT/$jour/FichierFailure/
dir_resultFilteredOut=/transfertCLINK/Share/RESULT_UAT/$jour/FichierFilteredOut/
if [[ `ls $dir_resultFailure | wc -l` -eq 0 ]] && [[`ls $dir_resultFilteredOut | wc -l` -eq 0 ]]
then
echo "repo is empty."
fi
You could have it in following way.
#!/bin/ksh
jour=$(date +%Y%m%d)
#Control if run is ok or not before sending mail
dir_resultFailure="/transfertCLINK/Share/RESULT_UAT/$jour/FichierFailure/"
dir_resultFilteredOut="/transfertCLINK/Share/RESULT_UAT/$jour/FichierFilteredOut/"
if [[ $(ls $dir_resultFailure | wc -l) -eq 0 ]] && [[ $(ls $dir_resultFilteredOut | wc -l) -eq 0 ]]
then
echo "repo is empty."
fi
Improvments/Fixes in OP's attempts:
Always wrap your variables values inside ".
Using backticks is deprecated now, use $(....) for saving variables values.
Your if condition was not correct, you should have spaces in between [[ and (.

Bash Script - Integer expression expected

With the below code, I keeping getting:
line 9: [: 8.8.8.8: integer expression expected
Unsure Why?
#!/bin/bash
sourceFile="file.log"
targetFile="2file.log"
ping="8.8.8.8"
while IFS='' read -r line || [[ -n "$line" ]]; do
echo "$line" >> "$targetFile"
sudo service networking restart
ping -q -c 5 "$ping"
if [ "$ping" -ne 0 ]; then
sed -n -e 8p "$2file.log"
fi
done < "$sourceFile"
Because you are trying to compare "8.8.8.8" (string) to 0 (integer)
ping="8.8.8.8"
if [ "$ping" -ne 0 ]; then
ping variable is string.
You are comparing a string value ("8.8.8.8") to an integer value (0)
You can retrieve the exit code of your ping command with $?
ping="8.8.8.8"
ping -q -c 5 "$ping"
ping=$?
if [ $ping -ne 0 ]; then
echo "NOTOK"
else
echo "OK"
fi
Check this post

BASH Script syntax error using grep on variable containing special characters

#!/bin/bash
password=$1
if [[ $# -gt 1 || $1 = "-h" ]]; then
echo 'Usage: pw | pw -h | pw password'
echo "Note: Valid passwords must be between 8-16 characters long.
contain at least 1 digit
contain at least 1 lowercase letter
contain at least 1 uppcase letter
contain one of # # $ % & * + - ="
fi
if [[ $# -lt 1 ]]; then
regex='0-9A-Z#*+#$%&a-z'
password=$( cat /dev/urandom | tr -dc '0-9A-Z#*+#$%&a-z' | head -c $(( 8 + $RANDOM % 8 )))
check=$( echo $password | grep -o ['#*+#$%&'] | wc -m )
while [[ $check -gt 2 || $check -lt 1 ]]
do
password=$( cat /dev/urandom | tr -dc '0-9A-Z#*+#$%&a-z' | head -c $(( 8 + $RANDOM % 8 )))
check=$( echo $password | grep -o ['#*+#$%&'] | wc -m )
done
echo $password
fi
if [[ $# = 1 ]]; then
password=$1
echo "$password" | grep [A-Z][a-z]
if [[ $? = 1 ]]; then
echo "Password must contain at least one upper or lowercase characer"
exit 2
fi
echo "$password" | grep [0-9]
if [[ $? = 1 ]]; then
echo "Password must contain at least one digit"
exit 3
fi
if [[ `echo "$password" | grep -o ['##$%&*+-'] 2>/dev/null` -gt 2 ]]; then
echo "You must only use one special character"
exit 4
fi
if [[ `echo "$password" | grep -o ['\#\#\$\%\&\*\+\-'] 2>/dev/null` -lt 1 ]]; then
echo "Password must contain at least one special character"
exit 5
fi
woc=$( echo "$password" | wc -m )
if [[ $woc -lt 8 || $woc -gt 16 ]]; then
echo "Password must be between 8 and 16 characters"
exit 6
fi
echo "$1 is a valid password"
fi
The first part of this script works perfectly and generates a random password 8-16 characters long with only one special character. Problems are on line 40 and 45, both giving me the same error "Syntax error: expecting operand "[special character]". I have tried creating variables and calling them, using the $? variable to check output and more. Unfortunately this error stays consistently even though the script does run correctly.
I fixed the code, it was a simple mistake. I forgot to include wc -m.
if [[ `echo "$password" | grep [\#\#\$\%\&\*\+\-] | wc -m` -lt 2 ]]

bash: if instruction that checks the number of lines from a variable fails

I have the following instruction:
if [[ ! `wc -l <<< $SILENT_LOG` -eq 1 -o ! `wc -l <<< $ACTIVE_LOG` -eq 1 ]] then
echo "There should be only a silent report log file!" >> $DEST_DIR/$RESULT_FILE
OK=0;
fi
OK should be set to 0 when SILENT_LOG or ACTIVE_LOG have 0 or more lines. The problem is that the following error is raised:
**./reportComparator.sh: line 26: syntax error near `-o'
./reportComparator.sh: line 26: `if [[ ! `wc -l <<< $SILENT_LOG` -eq 1 -o ! `wc -l <<< $ACTIVE_LOG` -eq 1 ]] then'**
Also, I tried to replace wc -l <<< $SILENT_LOG with echo $SILENT_LOG | wc-l but it still does not work.
First, the following syntax will not work:
$ [[ 1 -eq 1 -o 2 -eq 2 ]]
bash: syntax error in conditional expression
bash: syntax error near `-o'
In bash, you have two choices:
$ [[ 1 -eq 1 || 2 -eq 2 ]]
$ [ 1 -eq 1 -o 2 -eq 2 ]
For compatibility with plain POSIX shells, neither of the above should be used, the former because plain POSIX does not support [[ and the latter because plain POSIX shells cannot parse such long tests reliably. Instead use:
$ [ 1 -eq 1 ] || [ 2 -eq 2 ]
For the second issue, let's create a variable with three lines:
$ silent_log='one
> two
> three'
Now observe:
$ wc -l <<<$silent_log
1
$ wc -l <<<"$silent_log"
3
If you want the lines counted correctly, you need to double-quote your variables.
You have some syntax issues in your code.
For [[...] you can use:
if [[ $(wc -l < "$SILENT_LOG") -eq 1 || $(wc -l < "$ACTIVE_LOG") -eq 1 ]]; then
echo "There should be only a silent report log file!" >> $DEST_DIR/$RESULT_FILE
OK=0
fi

Is my syntax off or am I just doing this entirely wrong?

var1= grep "$1" ./[FILE] | wc -l
if [ -s ./[FILE] ] && [ "$var1" -eq 1 ]
then
echo "it worked"
fi
I'm trying to get var1 to have an integer value by using the command:
grep "$1" ./[FILE] | wc -l
I'm not sure if it is actually setting the value to the one that I assume the command is outputting because in my echo "$var1" it is echoing the value I expect. However, in my if statement:
if [ -s ./[FILE] ] && [ "$var1" -eq 1]
I continually get an illegal number error.
You're probably better off just doing
var1=$(grep -c "$1" ./[FILE])
-c, --count
Only a count of selected lines is written to standard output.
With regards to this:
var1= grep "$1" ./[FILE] | wc -l
if [ -s ./[FILE] ] && [ "$var1" -eq 1 ]
In shell scripting you can't have spaces on either side of the = in an assignment. The way that first line reads, you are running grep after assigning an empty string to var1. I suspect your intention was to capture the output of wc and assign that value to var1, which would be, as pointed out in another answer:
var1=$(grep "$1" ./[FILE] | wc -l)
However, as also pointed out, you can skip the wc part by changing that to
var1=$(grep -c "$1" ./[FILE])
One additional observation - if your [FILE] is zero-sized, grep isn't going to find anything, anyways, so there's really no need for that whole if ... && ... construct. Instead, those two lines could simply be:
if (( $(grep -c "$1" ./[FILE]) == 1 ))
then
echo "it worked"
....
If the echo bit is one single command, that can even be shortened to this:
(( $(grep -c "$1" ./[FILE]) == 1 )) && echo "it worked"

Resources