ksh + compare numbers – two ways - linux

the following example shows hot to compare numbers
I give here two different ways
one way with the ">" and "<"
and second way with "-gt" or "-lt"
both ways are work exactly
so what the differences between them ? or maybe there are not difference ?
example 1
ksh
a=1
b=2
[[ $a > $b ]] && echo ok
[[ $a < $b ]] && echo ok
ok
example 2
ksh
a=1
b=2
[[ $a -gt $b ]] && echo ok
[[ $a -lt $b ]] && echo ok
ok

In your examples there are no difference, but that is just an unfortunate choice of values for a and b.
-lt, -gt are for numeric comparison
< and > are for alphabetic comparison
$ a=12
$ b=6
$ [[ $a -lt $b ]] && echo ok
$ [[ $a &lt $b ]] && echo ok
ok

Related

Bash: Check if a string contain specific alphabets and comma

I am trying to parse and validate a string in Bash which is comma separated. The expected input is: X4,Y1,Z5
Conditions: The string should have only X,Y or Z alphabets, followed by any number. The string should not have any special characters other than comma. Please suggest.
X4,Y1,Z5 (This is OK)
Z2,y6,X1 (This is OK)
X3Y6,Z8 (This is not OK)
A1,B2,X8 (This is not OK)
N1P8* (This is not OK)
I have tried the following but this is not working as expected.
if [[ ! $str =~ ['!##$%^&*()_+'] ]] && [[ $str =~ [XYZxyz] ]]; then
echo "OK"
else
echo "Not OK"
fi
I suppose there are additional conditions of the problem that were implied but not emphasized, such as:
The numbers may have more then one digit.
Each of X,Y,Z letters should be used exactly once.
With that in mind, I think this code will do:
if [[ "$1" =~ ^[XxYyZz][0-9]+(,[XxYyZz][0-9]+){2}$ ]] &&
[[ "$1" =~ .*[Xx].* ]] &&
[[ "$1" =~ .*[Yy].* ]] &&
[[ "$1" =~ .*[Zz].* ]]
then
echo OK
else
echo Not OK
fi
Test cases:
#!/usr/bin/env bash
check() {
[[ "$1" =~ ^[XxYyZz][0-9]+(,[XxYyZz][0-9]+){2}$ ]] &&
[[ "$1" =~ .*[Xx].* ]] &&
[[ "$1" =~ .*[Yy].* ]] &&
[[ "$1" =~ .*[Zz].* ]]
}
test_check() {
# code - expected exit code
# value - string to test
while read code value; do
check "$value"
if [[ $? == $code ]]; then
echo -e "\e[1;32mPassed:\e[0m $value"
else
echo -e "\e[1;31mFailed:\e[0m $value"
fi
done
}
test_check <<EOF
0 x1,y2,z3
0 X1,Y2,Z3
1 x,y,z
1 1,2,3
1 1x,2y,3z
0 z1,x2,y3
1 a1,b2,c3
1 x1
1 x1,y2 z1
1 x1,x2
1 x1;y2;z3
1 x1,y2
1 x1,y2,y3
0 x100,Y500,z0
0 x011,y015,z0
1 x1,x2,y3,z4
1 x1,y1,z1 .
EOF
P.S.
If any of the X,Y,Z may appear in the string more than once or not appear at all, then [[ "$str" =~ ^[XxYyZz][0-9]+(,[XxYyZz][0-9]+)*$ ]] should work. I added here + for digits to appear one or more times after the letter, and quoted "$str" in case if there's a space in it (or, to be precise, any character from $IFS variable).

Bash -eq and ==, what's the diff?

Why this works:
Output=$( tail --lines=1 $fileDiProva )
##[INFO]Output = "OK"
if [[ $Output == $OK ]]; then
echo "OK"
else
echo "No Match"
fi
and this not?
Output=$( tail --lines=1 $fileDiProva )
##[INFO]Output = "OK"
if [[ $Output -eq $OK ]]; then
echo "OK"
else
echo "No Match"
fi
What's the difference?? between == and -eq?
Thanks!
-eq is an arithmetic test.
You are comparing strings.
From help test:
Other operators:
arg1 OP arg2 Arithmetic tests. OP is one of -eq, -ne,
-lt, -le, -gt, or -ge.
When you use [[ and use -eq as the operator, the shell attempts to evaluate the LHS and RHS. The following example would explain it:
$ foo=something
+ foo=something
$ bar=other
+ bar=other
$ [[ $foo -eq $bar ]] && echo y
+ [[ something -eq other ]]
+ echo y
y
$ something=42
+ something=42
$ [[ $foo -eq $bar ]] && echo y
+ [[ something -eq other ]]
$ other=42
+ other=42
$ [[ $foo -eq $bar ]] && echo y
+ [[ something -eq other ]]
+ echo y
y
Have a look at this explanation of if.
The first one == is in the section of string compare operators and it can only compare two strings.
The second one -eq is in the last section ARG1 OP ARG2(last one) and its documentation says "ARG1" and "ARG2" are integers.
-eq, -lt, -gt is only used for arithmetic value comparison(integers).
== is used for string comparison.

How to find min of two variables in linux

i have two variables
$a and $b
is there shell script command to assign the value of minimum variable to $c
i.e
$c = min($a,$b)
and some command that can work across all platforms hp-ux,aix,linux_x_64
thanks in advance
EDIT:
default shell is ksh
and below the script im trying to run
rm abc.log
near_dr=`sqlplus -s tcs384160/tcs#1234 <<\EOF
set pagesize 0 feedback off verify off heading off echo off
select max(sequence#) from v$archived_log where applied='YES' and thread#=1 and
dest_id=2;
exit;
EOF`
DR=`sqlplus -s tcs384160/tcs#1234 <<\EOF
set pagesize 0 feedback off verify off heading off echo off
select max(sequence#) from v$archived_log where applied='YES' and thread#=1 and
dest_id=3;
exit;
EOF`
safe_var=$([ $near_dr -le $DR ] && echo "$near_dr" || echo "$DR")
echo $safe_var;
ulimit=`expr $safe_var - 30`;
llimit=`expr $ulimit - 1000`;
echo $llimit;
echo $ulimit;
i=$llimit
while [ $i -le $ulimit ];
do
ls evdprd_1_${i}_*.arc>>abc.log;
let i=i+1;
done;
recover -s ttlhydnwr -c tphtpsd2<<EOF >> abc.log
ls -1 *.arc
exit
EOF
sed -e 's/[\t ]//g;/^$/d' abc.log > abc1.log
awk '++seen[$0] == 2' abc1.log > actual.log
please ignore the sqlplus parts as those are working fine the only problem is the $safe_var needing the minimum of the two values
There is no function, but you can create it:
(( $a <= $b )) && echo "$a" || echo "$b"
The condition && action1 || action2 does evaluate the condition. If it is true, then perform action1; otherwise, perform action2.
To store the result into a variable, do:
min=$( (( $a <= $b )) && echo "$a" || echo "$b" )
Update
It seems that the $( (( )) ) syntax is giving problems. Hence, let's replace it to:
[ $a -le $b ] && echo "$a" || echo "$b"
or assigning value:
min=$([ $a -le $b ] && echo "$a" || echo "$b")
Sample
$ a=3
$ b=4
$ [ $a -le $b ] && echo "$a" || echo "$b"
3
$ b=1
$ [ $a -le $b ] && echo "$a" || echo "$b"
1
$ b=3
$ [ $a -le $b ] && echo "$a" || echo "$b"
3
You could do in this way too:
x=1
y=2
echo $(($x<$y?$x:$y))
1
To store value in other variable:
z=$(($x<$y?$x:$y)) #Min
z=$(($x<=$y?$x:$y)) #Min and equal
z=$(($x>$y?$x:$y)) #Greater
z=$(($x>=$y?$x:$y)) #Greater and equal
In ksh, this works fine
$ near_dr=5 DR=10
$ save_var=$(( near_dr < DR ? near_dr : DR )) ; echo $save_var
5
$ near_dr=15 DR=10
$ save_var=$(( near_dr < DR ? near_dr : DR )) ; echo $save_var
10
$ near_dr=15 DR=15
$ save_var=$(( near_dr < DR ? near_dr : DR )) ; echo $save_var
15
So you can write a function:
min() {
echo $(( $1 < $2 ? $1 : $2 ))
}
safe_var=$(min $near_dr $DR)
This is the same as #Liaraz's answer, except "Variables can be referenced by name within an arithmetic
expression without using the parameter expansion syntax." (ksh man page, section Arithmetic evaluation)
Ksh93 custom arithmetic function example:
function .sh.math.min a b {
.sh.value=$(( a<b ? a : b ))
}
$ echo $(( min(1,3) ))
1
$ echo $(( min(5,3) ))
3
if you are sure the value of variables are integers, use #fedorqui's answer. It's short and neat.
however, if you are not sure about that, they could be e.g. float numbers:
kent$ a=3.57
kent$ b=13.5
kent$ (($a < $b)) && echo "y" || echo "n"
bash: ((: 3.57 < 13.5: syntax error: invalid arithmetic operator (error token is ".57 < 13.5")
n
this would work for all cases:
kent$ awk -v a="$a" -v b="$b" 'BEGIN{print (a>b)?b:a}'
3.57

Bash: String contains hyphen

I am trying to see if string1 contains another string2. I do this in this manner:
a=$(tempfile)
echo "eafg" > $a
if [[ $a == *e* ]]
then
echo "contains"
fi
Now I try to see if a string contains a hyphen:
a=$(tempfile)
echo "22:00:00-02:00" > $a
if [ $a == *-* ]
then
echo "contains"
fi
It doesn't work. I also tried:
if [ $a == *--* ]
if [ $a == *---* ]
if [[ $a == *-* ]]
if [[ $a == *--* ]]
if [[ $a == *---* ]]
With no success...
Thanks in advance
Following piece of code brings problems
a=$(tempfile)
echo "22:00:00-02:00" > $a
Here you are writing to a file $a and then try to do string comparison.
Try following
a="22:00:00-02:00"
if [[ $a == *-* ]]
then
echo "contains"
fi
You redirected the string to a file, so read it from the file while comparing.
The variable a contains the name of the file and not the contents.
Say:
if [ $(<$a) == *-* ];
then
echo "contains"
fi
The following
if [[ $a == *e* ]];
then
echo "contains"
fi
worked for you because the variable holding the name of the file contained the letter e.

compared two parameters using "<" in shell

let's assign like this:
a=7
b=29
[[ $a < $b ]] && echo dasf
it doesn't work!!
however, when
a=1
with b and command same, it works well.
That's very funky! Can somebody explain that?
You're comparing the variables lexically, not numerically.
Try
[[ $a -lt $b ]] && echo smaller
or
(( $a < $b )) && echo smaller

Resources