shell scripting pitfall: string/number conversions

I create quite a few WordPress installs for my partner, Morgan, to develop from, and we have a non-trivial number of changes we implement for each new WordPress install.  I wrote a simple install script that does everything so that Morgan can easily create a new WP install whenever she needs one.

One of the things I do in the script is add a new DNS record to a zone file in BIND and update the named server.  (Tiny bit of a background: DNS updating works by having serial numbers be larger that the previous update’s serial–these serials are typically a 10-digit numeric form of date+version (eg, the serial 2011072602 is July 26th, 2011 (20110726) & the (02) 2nd revision for today).) If my shell script needed to update the serial number which was already changed today, it would need to increment the version, which gets read in as a string.  That isn’t a big deal, as you can easily cast a string to be a number by doing $((variable)).  But it needs to be replaced by a 2-digit version again, so I used awk to make sure it was

ver="02"
echo $ver+1
02+1
echo $((ver+1))
03

That works fine, but what if you’re on the 08th revision for the day?
ver="08"
echo $ver+1
08+1
echo $((ver+1))
08: value too great for base (error token is "08")

Why is that happening?

Well, the shell is trying to be clever: it knows that numbers that start with 0x are going to be in hex, and numbers that start with 1-9 are going to be decimals, and it thinks that numbers that start with 0 are octal (that is, base 8, or 01234567) so it doesn’t know what the heck an ’8′ is (its like trying to add 3+a in decimal–it just doesn’t compute).  To get around this, I need to force my variable “ver” to be numeric without the leading 0.

I use awk’s printf to do this as it seemed like the easiest thing (I really like awk).

ver="08"
ver2=`echo $ver | awk '{printf( "%d", $1 )}'`
echo $((ver2+1))
9

I then have to ensure that I have a 2-digit number to put back together with today’s date to ensure that my serial number is complete.  I again use awk’s printf:
ver3=`echo $((ver2+1)) | awk '{printf( "%02d", $1 )}'`
echo ver3
09

While converting from 08 to 8 to 9 and back to the 2-digit 09 is a little convoluted, being able to do different common base (eg hex, octal) in the shell is handy (after all, Real Men code in the shell, right?).

Feel free to contact me if you’d like a copy of the script.

Share:
  • Twitter
  • Facebook
  • StumbleUpon
  • Google Bookmarks
This entry was posted in awk, linux, shell scripting. Bookmark the permalink.

4 comments on “shell scripting pitfall: string/number conversions

  1. Careful when you get to update 99+1.

  2. it is very useful, helps me a lot…normal books does not really write these tricks

  3. Just wanted to say thanks for posting, it helped me along! Oh bash scripting…

Leave a Reply

Your email address will not be published. Required fields are marked *

*

11,791 Spam Comments Blocked so far by Spam Free Wordpress

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>