how to compare real/float while using "AND" .(unix) - unix

I'm new to shell scripting, I have written a small script to check if the input is in the specified (integer) range:
echo "Enter number btw 50 and 100:"
read num
if [ $num -le 100 -a $num -ge 50 ];
then
echo "you are in limits."
else
echo "you are out of limits."
fi
How can I check if a number is in a real/floating range?

You can't with sh/ksh1/bash(/zsh?) -- integer arithmetic only.
You can do something like
if [ "$(echo "50 <= $num && $num <= 100" | bc)" = "1" ]; then
echo "you are in limits."
else
echo "you are out of limits."
fi
(1 - ksh93 can do floating point arithmetic)

Related

maintaining checkpoints using Unix shell script

The following code does not work very effectively when it comes to managing the checkpoints. Can some give some better idea?
MainScriptName="MainScriptName-"
Checkpoints="$MAIN/Checkpoints"
StepNo="02"
StepName="MyStepName"
MainLogPathFilename="$LogPath$MainScriptName$LogFilenamets.csv"
fileCount=0
fileCount=`find $Checkpoints -maxdepth 1 -name "$MainScriptName$StepNo.lck" | wc -l`
SECONDS=0
executions_status=""
StepStarted="$(date +'%d/%m/%Y %H:%M')"
echo "Step No : $StepNo $StepStarted"
if [ $fileCount -eq 0 ]
then
$hivef $MAIN/MyscriptName/Date.hql >> $LogPath/$MainScriptName.log 2>&1
if [ "$?" -ne 0 ]
then
duration=$SECONDS
echo "$StepName, $StepStarted, $StepCompleted, $(($duration / 60)), Failed" >> $MainLogPathFilename
echo "Failed !"
exit 10
else
touch $Checkpoints/$MainScriptName$StepNo.lck
executions_status="Success"
fi
else
executions_status="Skipped"
fi
echo "$executions_status"
StepCompleted="$(date +'%d/%m/%Y %H:%M')"
duration=$SECONDS
echo "$StepNo, $StepName, $StepStarted, $StepCompleted, $(($duration / 60)), $executions_status" >> $MainLogPathFilename
and then simply read it if exists then skip it.
echo "Script Name : " $MainScriptName "- Started"
StepNo="01"
fileCount=0
fileCount=`find $Checkpoints -maxdepth 1 -name "$MainScriptName$StepNo.lck" | wc -l`
StepName="Build_Report"
SECONDS=0
executions_status=""
StepStarted="$(date +'%d/%m/%Y %H:%M')"
echo "File Count : $fileCount"
echo "Step No : $StepNo $StepStarted"
if [ $fileCount -eq 0 ] then
$hivef $HDP_MAIN/CODE/TXN/HiveQuery.hql > $LogPath/$MainScriptName.log 2>&1
query1result=$?
ScriptError="-1"
ScriptError=`cat "$LogPath/$MainScriptName.log" | grep "(No such file or directory)\|Error opening session" | wc -l`
if [ $query1result -ne 0 ] || [ $ScriptError -gt 0 ]
then
duration=$SECONDS
echo "$StepName, $StepStarted, $StepCompleted, $(($duration / 60)), Failed" >> $MainLogPathFilename
echo "Failed !"
exit 10
else
touch $Checkpoints/$MainScriptName$StepNo.lck
executions_status="Successfully Completed."
fi
else
executions_status="Skipped"
fi
echo "$executions_status"
StepCompleted="$(date +'%d/%m/%Y %H:%M')"
duration=$SECONDS
echo "$StepNo, $StepName, $StepStarted, $StepCompleted, $(($duration / 60)), $executions_status" >> $MainLogPathFilename

Date validation in Unix shell script (ksh)

I am validating the date in Unix shell script as follow:
CheckDate="2010-04-09"
regex="[1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-3][0-9]"
if [[ $CheckDate = *#$regex ]]
then
echo "ok"
else
echo "not ok"
fi
But ksh it is giving output as not okay.. pls help.. i want output as ok
Here is my little script (written in Solaris 10, nawk is mandatory... sorry...). I know if you try to trick it by sending an alphanumeric you get an error on the let statements. Not perfect, but it gets you there...
#!/usr/bin/ksh
# checks for "-" or "/" separated 3 field parameter...
if [[ `echo $1 | nawk -F"/|-" '{print NF}'` -ne 3 ]]
then
echo "invalid date!!!"
exit 1
fi
# typeset trickery...
typeset -Z4 YEAR
typeset -Z2 MONTH
typeset -Z2 DATE
let YEAR=`echo $1 | nawk -F"/|-" '{print $3}'`
let MONTH=`echo $1 | nawk -F"/|-" '{print $1}'`
let DATE=`echo $1 | nawk -F"/|-" '{print $2}'`
let DATE2=`echo $1 | nawk -F"/|-" '{print $2}'`
# validating the year
# if the year passed contains letters or is "0" the year is invalid...
if [[ $YEAR -eq 0 ]]
then
echo "Invalid year!!!"
exit 2
fi
# validating the month
if [[ $MONTH -eq 0 || $MONTH -gt 12 ]]
then
echo "Invalid month!"
exit 3
fi
# Validating the date
if [[ $DATE -eq 0 ]]
then
echo "Invalid date!"
exit 4
else
CAL_CHECK=`cal $MONTH $YEAR | grep $DATE2 > /dev/null 2>&1 ; echo $?`
if [[ $CAL_CHECK -ne 0 ]]
then
echo "invalid date!!!"
exit 5
else
echo "VALID DATE!!!"
fi
fi
You can try this and manipulate
echo "04/09/2010" | awk -F '/' '{ print ($1 <= 04 && $2 <= 09 && match($3, /^[0-9][0-9][0-9][0-9]$/)) ? "good" : "bad" }'
echo "2010/04/09" | awk -F '/' '{ print ( match($1, /^[0-9][0-9][0-9][0-9]$/) && $2 <= 04 && $3 <= 09 ) ? "good" : "bad" }'
Please find the below code works as your exception.
export checkdate="2010-04-09"
echo ${checkdate} | grep '^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$'
if [ $? -eq 0 ]; then
echo "Date is valid"
else
echo "Date is not valid"
fi

Unix- How to return +,-,0 depending on integer inputted?

I would like to create shell script that echos a + if the inputted integer is a positive, echos a "-" if the inputted integer is a negative, and echos a "0" if its not any of those.
So my script is like this:
echo "Enter an Integer"
read declare -i var1
if((var1>0))
then
echo +
elif (( var1<0))
then echo -
else echo 0
fi
I keep getting a bad variable name error and var1 not found.
I got the script to work by separating the read and declare lines.
echo "Enter an Integer"
declare -i var1
read var1
if((var1>0))
then
echo +
elif (( var1<0))
then echo -
else echo 0
fi
Console log (running on OS X):
$ bash e.sh
Enter an Integer
972
+
$ bash e.sh
Enter an Integer
-32
-
$ bash e.sh
Enter an Integer
0
0
I believe you want to read and then test your values. Something like
echo "Enter an Integer"
read var1
if [[ "$var1" -gt 0 ]]
then
echo +
elif [[ "$var1" -lt 0 ]]
then
echo -
else
echo 0
fi
works here.

how to solve nested if issue

I am new to UNIX ... I am trying to write a bash script that takes two integers from the user and prints out the even numbers between these two numbers using an if condition. I am stuck on the nested if "an unexpected token near else" error message appears. I do not know what the error is about. Any help?
This is what I have done so far:
echo plz enter first number
read n1
echo plz enter second number
read n2
start=$n1
end=$n2
if [ start < end ] then
for (c=start;c<=end;c++)
do
if [ $((c % 2 )) -eq 0 ]; then
echo $c
fi
done
else
echo "not bigger"
fi
I think I would recommend a different approach:
((start % 2)) && ((start = 1 + start))
while ((start < end))
do
echo ${start}
(( start += 2))
done
I have tried like this:-
echo "Enter first number"
read first
echo "Enter second number"
read second
start=$first
endLine=$second
while [ $start -le $endLine ]
do
if [ $((start % 2 )) -eq 0 ]
then
echo $start "is an even number"
#else
# echo $start "is an odd number"
fi
start=`expr $start + 1`
done
You need to insert either a semicolon or a newline before the first "then":
if [ start < end ] ; then
^

Convert decimal to hexadecimal in UNIX shell script

In a UNIX shell script, what can I use to convert decimal numbers into hexadecimal? I thought od would do the trick, but it's not realizing I'm feeding it ASCII representations of numbers.
printf? Gross! Using it for now, but what else is available?
Tried printf(1)?
printf "%x\n" 34
22
There are probably ways of doing that with builtin functions in all shells but it would be less portable. I've not checked the POSIX sh specs to see whether it has such capabilities.
echo "obase=16; 34" | bc
If you want to filter a whole file of integers, one per line:
( echo "obase=16" ; cat file_of_integers ) | bc
Hexidecimal to decimal:
$ echo $((0xfee10000))
4276158464
Decimal to hexadecimal:
$ printf '%x\n' 26
1a
bash-4.2$ printf '%x\n' 4294967295
ffffffff
bash-4.2$ printf -v hex '%x' 4294967295
bash-4.2$ echo $hex
ffffffff
Sorry my fault, try this...
#!/bin/bash
:
declare -r HEX_DIGITS="0123456789ABCDEF"
dec_value=$1
hex_value=""
until [ $dec_value == 0 ]; do
rem_value=$((dec_value % 16))
dec_value=$((dec_value / 16))
hex_digit=${HEX_DIGITS:$rem_value:1}
hex_value="${hex_digit}${hex_value}"
done
echo -e "${hex_value}"
Example:
$ ./dtoh 1024
400
Try:
printf "%X\n" ${MY_NUMBER}
In my case, I stumbled upon one issue with using printf solution:
$ printf "%x" 008
bash: printf: 008: invalid octal number
The easiest way was to use solution with bc, suggested in post higher:
$ bc <<< "obase=16; 008"
8
In zsh you can do this sort of thing:
% typeset -i 16 y
% print $(( [#8] x = 32, y = 32 ))
8#40
% print $x $y
8#40 16#20
% setopt c_bases
% print $y
0x20
Example taken from zsh docs page about Arithmetic Evaluation.
I believe Bash has similar capabilities.
xd() {
printf "hex> "
while read i
do
printf "dec $(( 0x${i} ))\n\nhex> "
done
}
dx() {
printf "dec> "
while read i
do
printf 'hex %x\n\ndec> ' $i
done
}
# number conversion.
while `test $ans='y'`
do
echo "Menu"
echo "1.Decimal to Hexadecimal"
echo "2.Decimal to Octal"
echo "3.Hexadecimal to Binary"
echo "4.Octal to Binary"
echo "5.Hexadecimal to Octal"
echo "6.Octal to Hexadecimal"
echo "7.Exit"
read choice
case $choice in
1) echo "Enter the decimal no."
read n
hex=`echo "ibase=10;obase=16;$n"|bc`
echo "The hexadecimal no. is $hex"
;;
2) echo "Enter the decimal no."
read n
oct=`echo "ibase=10;obase=8;$n"|bc`
echo "The octal no. is $oct"
;;
3) echo "Enter the hexadecimal no."
read n
binary=`echo "ibase=16;obase=2;$n"|bc`
echo "The binary no. is $binary"
;;
4) echo "Enter the octal no."
read n
binary=`echo "ibase=8;obase=2;$n"|bc`
echo "The binary no. is $binary"
;;
5) echo "Enter the hexadecimal no."
read n
oct=`echo "ibase=16;obase=8;$n"|bc`
echo "The octal no. is $oct"
;;
6) echo "Enter the octal no."
read n
hex=`echo "ibase=8;obase=16;$n"|bc`
echo "The hexadecimal no. is $hex"
;;
7) exit
;;
*) echo "invalid no."
;;
esac
done
This is not a shell script, but it is the cli tool I'm using to convert numbers among bin/oct/dec/hex:
#!/usr/bin/perl
if (#ARGV < 2) {
printf("Convert numbers among bin/oct/dec/hex\n");
printf("\nUsage: base b/o/d/x num num2 ... \n");
exit;
}
for ($i=1; $i<#ARGV; $i++) {
if ($ARGV[0] eq "b") {
$num = oct("0b$ARGV[$i]");
} elsif ($ARGV[0] eq "o") {
$num = oct($ARGV[$i]);
} elsif ($ARGV[0] eq "d") {
$num = $ARGV[$i];
} elsif ($ARGV[0] eq "h") {
$num = hex($ARGV[$i]);
} else {
printf("Usage: base b/o/d/x num num2 ... \n");
exit;
}
printf("0x%x = 0d%d = 0%o = 0b%b\n", $num, $num, $num, $num);
}
For those who would like to use variables, first export it by running:
export NUM=100
Then run:
printf "%x\n" $NUM
Else, you can you can ignore the use case of the variables and run it directly as shown below:
printf "%x\n" 100
NB:Substitute NUM with the variable name of your choice.
Exporting makes it an environmental variable(global).
Wow, I didn't realize that printf was available at the shell!
With that said, I'm surprised no-one commented about putting the printf into a shell script (which then you could put in your personal bin directory if you wanted).
echo "printf "0x%x\n" $1" > hex
chmod +x hex
Now just run:
./hex 123
It returns:
0x7b

Resources