57

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?

2
  • 3
    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. Commented Jan 21, 2017 at 20:00
  • This error comes from "leading zero" error AKA any 0 digit that comes before the first non-zero representation in bash. examples ( for example 01 ,002 , 0000003 etc... ) Commented Sep 19, 2019 at 14:44

8 Answers 8

132

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))
Sign up to request clarification or add additional context in comments.

10 Comments

You can also force the base-10 interpretation: $((10#$hour+1)).
This is not working for my bash and negative numbers: lat=-048 ; latd=${lat#0} ; echo $latd ; echo $((latd-1)) gives me -048 and then the same error.
@LuisA.Florit: Of course, as #0 removes zero from the start of the string, and there's a - instead. Use shopt -s extglob ; latd=${latd#?(-)0}.
The problem with that is that you get the absolute value (in the example, 47 instead of -49. It seems this needs a longer oneliner maybe with sed,bc or something that I wanted to avoid since mine is inside a big loop. I hate this octal thing bash do. It should be possible to configure it with a shopt.
Numbers with an optional leading + or - can be handled with $((${hour%%[^-+]*}10#${hour#[-+]}))
|
17

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.

Comments

12

You could also use bc

hour=8
result=$(echo "$hour + 1" | bc)
echo $result
9

1 Comment

It worked for me so +1 however, I was looking for some simple soln like result=int("$hour + 1")
4

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.)"

Comments

3

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

2 Comments

This just produces the string 08+0
what shell are you using @JimGarrison
2

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.

Comments

1

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.

Comments

1

How about sed?

hour=`echo $hour|sed -e "s/^0*//g"`

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.