37

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?

  • OP, your accepted answer is great - for your specific case, but it doesn't match the question title. – einpoklum - reinstate Monica Sep 13 '16 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 '18 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 '18 at 8:03
49
  • 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.

  • 2
    thx, very detailed! btw, echo $((011)) $((10#011)) is another good example that outputs 9 11 – Aquarius Power Apr 29 '13 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. – Luis A. Florit Feb 12 '16 at 0:17
  • plus=$((10#01)) – Dr Beco Mar 24 '17 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.