43

I have this:

date +"%H hours and %M minutes"

I use festival to say it up.. but it says like: "zero nine hours".. I want it to say "nine hours"!

but date always give me 09... so I wonder if bash can easly make that become just 9?

in the complex script I tried like

printf %d 09

but it fails.. not octal :(

any idea?

3
  • OP, your accepted answer is great - for your specific case, but it doesn't match the question title.
    – einpoklum
    Sep 13, 2016 at 8:47
  • @ilkkachu the old title was key in me finding this question, looking for forcing decimal interpretation of octal-format numbers.
    – muru
    Jun 4, 2018 at 7:55
  • @muru, yeah, I thought if I could stick the note about octal there, but didn't come up with a nice phrasing. You could change it of course, at least you know what you searched for? The answers and question still mainly seem to be about removing the leading zero.
    – ilkkachu
    Jun 4, 2018 at 8:03

4 Answers 4

59
  • In your case, you can simply disable zero padding by append - after % in the format string of date: %-H

    By default, date pads numeric fields with zeroes. The following optional flags may follow '%':

    • - (hyphen) do not pad the field
    • _ (underscore) pad with spaces
    • 0 (zero) pad with zeros
    • ^ use upper case if possible
    • # use opposite case if possible

    See date manual

  • If you want to interpret number in different base, in bash

    • Constants with a leading 0 are interpreted as octal numbers.
    • A leading 0x or 0X denotes hexadecimal.
    • Otherwise, numbers take the form [base#]n, where base is a decimal number between 2 and 64 representing the arithmetic base, and n is a number in that base

    So, to interpret a number as decimal, use 10#n form, eg. 10#09

    echo $((10#09*2))
    18
    

    See Arithmetic Evaluation section of bash manual.

3
  • 2
    thx, very detailed! btw, echo $((011)) $((10#011)) is another good example that outputs 9 11 Apr 29, 2013 at 21:10
  • 1
    This does not work for negative numbers: lat=048 ; latd=${lat#0} ; echo $((latd-1)) works, but lat=-048 ; latd=${lat#0} ; echo $((latd-1)) doesn't. Feb 12, 2016 at 0:17
  • plus=$((10#01))
    – DrBeco
    Mar 24, 2017 at 23:21
2

If you're trying to do comparisons in decimal with date values, I've found this method to be very effective:

let mymin=$(date '+1%M') ; let mymin=$mymin%100

That always yields a decimal value. So I can do this:

if [[ $mymin -le 1 ]]; then   # only 0 and 1 are true.

There's no problem with 08 or 09 this way. Using %10 instead of %100 gives you ten-minute ranges from 0 through 9. I also find the following gives decimal values, without leading zeros:

echo "$((10#$(date +%M)))"
2

Portably, you can easily remove a leading 0 from a variable. This leaves the variable unchanged if there is no leading 0.

eval $(date +"h=%H m=%M")
h=${h#0}
m=${m#0}
say "$h hours and $m minutes"

In bash, ksh or zsh, you can use ksh's additional glob patterns to remove any number of leading 0s. In bash, run shopt -s extglob first. In zsh, run setopt kshglob first.

eval $(date +"h=%H m=%M")
h=${h#+(0)}
m=${m#+(0)}
say "$h hours and $m minutes"
1

In general in bash:

test ${#number} -eq 2 && number=${number#0}

resulting in

date +"%H %M" | 
{ read hours minutes
hours=${hours#0}
minutes=${minutes#0}
echo "${hours} hours and ${minutes} minutes"; }

Or, different:

date +"%H hours and %M minutes" | sed -n -e 's/0\([0-9]\)/\1/g' -e p

I am surprised that date does not have appropriate format options.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .