Error Value is too great for base in bash - bash

The below bash script is written for finding the files which are modified with in the last T second where T is supplied from the command line.
if [ $# -ne 1 ]; then
echo "Wrong number of argument"
exit 1
fi
for f in *
do
if [ -x "$f" ]; then
currenttime=$(date | awk '{print $4}')
modify=$(date -r "$f" | awk '{print $4}')
d_c=${currenttime:0:2}
m_c=${currenttime:3:2}
s_c=${currenttime:6:2}
d_m=${modify:0:2}
m_m=${modify:3:2}
s_m=${modify:6:2}
let "1d_c *= 24"
let "m_c *= 60"
let "second_c = d_c+m_c+s_c"
let "d_m *= 24"
let "m_m *= 60"
let "second_m=d_m+m_m+s_m"
let "diff=second_c-second_m"
if [ $diff -lt $1 ]; then
echo $f
fi
fi
do
ne
But I am getting the below error in that.
./recent.sh: line 46: let: 09: value too great for base (error token is "09")
./recent.sh: line 47: let: 09: value too great for base (error token is "09")
./recent.sh: line 49: let: 09: value too great for base (error token is "09")
I know that this error is coming due to the large value in the variable and I have to make the variable decimal but I don't know how to do it in my case(inside the let command, how to make them decimal).

The problem is that 09, due to the leading 0, is interpreted as octal, whereas (as you've surmised) you need it to be interpreted as decimal.
To fix this, you need to bypass let's normal convert-variable-to-number process. Instead of writing, for example, this:
let "second_c = d_c+m_c+s_c"
you should write this:
let "second_c = 10#$d_c + 10#$m_c + 10#$s_c"
By prepending $, you're asking Bash to substitute in the variable-value as a string ā€” so, for example, if d_c is 09, then 10#$d_c will be 10#09. The 10# prefix tells let that the number should be interpreted as base-10.
Actually, on second thought, it's probably best to do this when you initially populate these variables; for example:
d_c=$(( 10#${currenttime:0:2} ))
That way you don't have to do it everywhere that you use them. (And also, it puts any errors closer to their source, which makes debugging easier.)

Related

Bash arithmetic expansion with for loop

I am trying to write a loop that uses command line arguments to determine the range over which it operates. As of now I've tried the following:
let a=$1
let best=$2
for ((i=a ; i < best ; i++)); do
let bwd_g = $((20 - i))
echo $bwd_g
done
when I call ./test.sh the following output is produced:
./test.sh: line 9: let: =: syntax error: operand expected (error token is "=")
I've spent a large amount of time on coming up with different variants of this code but to no avail and have tried googling the error message.
Though I am not fully sure about your requirement, but to fix your specific error, try wrapping let with " and it should fly then, like (there shouldn't be any spaces between variable name(s) and =):
cat script.sh
let a=$1
let best=$2
for ((i=a ; i < best ; i++)); do
let "bwd_g = $((20 - i))"
echo $bwd_g
done
You should use $((.....)) for doing operations in bash, so better use following rather than let:
cat script.sh
a=$1
best=$2
for ((i=a ; i < best ; i++)); do
bwd_g=$((20 - i))
echo $bwd_g
done
I think the issue was with blank spaces on line 4. Please check below.
let a=$1
let best=$2
for ((i=a ; i < best ; i++)); do
let bwd_g=$((20 - i))
echo $bwd_g
done
and I ran it as
bash script.sh 5 10

Addin 0 in front of one digit number/text in bash script

I would like to compare a number, which is the output of a command, with a constant and do some manipulation. That is, if $id < 10, I want to see 590$id and if it is above 10, I want to see 59$id.
I found that expr doesn't working here:
ID=3
NUM=59$ID
if [ `expr $ID` -lt 10]; then
NUM=590$ID
fi
echo $NUM
The output of the code is 593 and not 5903. Even, $(($ID + 5900)) -lt 5910 writes 593.
How can I fix that?
Could you please try following.
cat script.sh
#!/bin/bash
ID=$(printf "%02d" 3 )
##NUM=59$ID ##Commented this to check if, condition is getting satisfied or not. Doesn't seem to be fit here.
(( $ID < 10 )) && NUM="59$ID"
echo "$NUM"
Output will be 5903 after running above code.
Don't use expr. It's old and tricky.
Don't use backticks `. They are discouraged and $( ... ) is preferred.
For arithmetic comparisons use arithmetic expansions. Just
if (( ID < 10 )); then
Note that bash is space aware and your script has a syntax error, it is missing a space - the 10]; should be 10 ];.
Note that by convention uppercase variables should be used for exported variables.
Looking at your code I think you just want:
NUM=$((5900 + ID))

bash float comparison and (standard_in) 1: syntax error

I have this piece of code where I am getting (standard_in) 1: syntax error from the third line:
valueInFloat=printf "%.2g" $temp
tempFloat=printf "%.1f" $value2
compare_result=`echo "$tempFloat < $valueInFloat" |bc -l`
if [[ -z $compare_result ]]
then ...
I am trying to do float value comparison in bash.
Note that, if I comment out the third line and put compare_result=0, the error goes away.
There are situations in which printf can generate floating point values that bc won't recognise. Specifically, something like:
pax> printf "%.2g\n" 42456456457357357
4.2e+16
pax> echo '4.2e+16 > 1.0' | bc -l
(standard_in) 1: syntax error
I suggest you stick with the %f variant. It will always generate the form [āˆ’]999.999 as per the ISO C standard, which bc will have no trouble with (unless you start getting into infinities or NaNs). The %g variant generates either that format or the %e format [āˆ’]9.999eĀ±99 depending on the value and precision requested.
In addition, your test is wrong. The -z test will be true if the string is empty, and your string will either be 1 or 0 depending on the result of the comparison. A better test would be (assuming you wanted to rest if the test was positive:
if [[ ${compare_result} -eq 1 ]]
Either of $tempFloat or $valueInFloat has no value.

confirm numeric character of variable

I need to do an operation but something is wrong in my code in bash
I have 4 variables, km1, km2, km3, km4.
I want to sum the 4 variables except when the value is "CLOSED"
3.200
CLOSED
1.800
0.600
When I do the following sum, there is an error...I thing my variables are not numeric, any help? How can I force them to be numeric and then do the sum?
let km=$km1+$km3+$km4
echo $km
./sum.sh: line 41: let: km=3.200: syntax error: invalid arithmetic operator (error token is ".200")
km1=3.200
km2=CLOSED
km3=1.800
km4=0.600
total=`LC_ALL=C echo "$km1 $km2 $km3 $km4"|awk '{sum += $1+$2+$3+$4}END {print sum}'`
Not that good with awk but i think the above can help. total the is sum of all vars
There are 2 issues with you code. The first one is that you are trying to work with values other than integers. Bash only does integers. You can round up the values to integers using bc (An arbitrary precision calculator language). The second issue is that you are trying to do math on strings. So consider the code below:
#!/bin/bash
km1=3.200;
km2="CLOSED";
km3=1.800;
km4=0.600;
km1=$(echo "$km1/1" | bc)
km3=$(echo "$km3/1" | bc)
km4=$(echo "$km4/1" | bc)
array=($km1 $km2 $km3 $km4)
for i in ${array[#]}; do
case $i in
*[0-9]*)
(( result+=$i ))
esac
done
echo $result

Convert string into integer in bash script - "Leading Zero" number error

In a text file, test.txt, I have the next information:
sl-gs5 desconnected Wed Oct 10 08:00:01 EDT 2012 1001
I want to extract the hour of the event by the next command line:
hour=$(grep -n sl-gs5 test.txt | tail -1 | cut -d' ' -f6 | awk -F ":" '{print $1}')
and I got "08". When I try to add 1,
14 echo $((hour+1))
I receive the next error message:
./test2.sh: line 14: 08: value too great for base (error token is "08")
If variables in Bash are untyped, why?
See ARITHMETIC EVALUATION in man bash:
Constants with a leading 0 are interpreted as octal numbers.
You can remove the leading zero by parameter expansion:
hour=${hour#0}
or force base-10 interpretation:
$((10#$hour + 1))
what I'd call a hack, but given that you're only processing hour values, you can do
hour=08
echo $(( ${hour#0} +1 ))
9
hour=10
echo $(( ${hour#0} +1))
11
with little risk.
IHTH.
You could also use bc
hour=8
result=$(echo "$hour + 1" | bc)
echo $result
9
Here's an easy way, albeit not the prettiest way to get an int value for a string.
hour=`expr $hour + 0`
Example
bash-3.2$ hour="08"
bash-3.2$ hour=`expr $hour + 0`
bash-3.2$ echo $hour
8
In Short: In order to deal with "Leading Zero" numbers (any 0 digit that comes before the first non-zero) in bash
- Use bc An arbitrary precision calculator language
Example:
a="000001"
b=$(echo $a | bc)
echo $b
Output: 1
From Bash manual:
"bc is a language that supports arbitrary precision numbers with interactive execution
of statements. There are some similarities in the syntax to the C programming lan-
guage. A standard math library is available by command line option. If requested, the
math library is defined before processing any files. bc starts by processing code from
all the files listed on the command line in the order listed. After all files have
been processed, bc reads from the standard input. All code is executed as it is read.
(If a file contains a command to halt the processor, bc will never read from the standard input.)"
Since hours are always positive, and always 2 digits, you can set a 1 in front of it and subtract 100:
echo $((1$hour+1-100))
which is equivalent to
echo $((1$hour-99))
Be sure to comment such gymnastics. :)
The leading 0 is leading to bash trying to interpret your number as an octal number, but octal numbers are 0-7, and 8 is thus an invalid token.
If I were you, I would add some logic to remove a leading 0, add one, and re-add the leading 0 if the result is < 10.
How about sed?
hour=`echo $hour|sed -e "s/^0*//g"`

Resources