How do I increment an alphanumeric string using awk?
February 5, 2009 6:41 PM   Subscribe

How do I increment an alphanumeric string using awk?

I have a utility that shows me the WWID of the first port of a dual port HBA card. The second port is not explicitly listed, however it is always one digit higher than the first.

So, given that port a = 500062b0000eb5a4 -- then I know port b = 500062b0000eb5a5.

So I run my util and pipe it to awk, so it returns the WWID and nothing else:


# ./util | awk '/WWID/ {print $3}'

500062b0000eb5a4


Now I need awk to increment the alphanumeric WWID, so I can add these WWIDs to a host group on my storage enclosures. Here's where my awk-fu is weak. I've tried various things (quotes, etc) but here's a typical example of how far I'm getting:


#./util | awk '/WWID/ {print $3++}'
500063


Is there an economical way to get awk to not choke on the first alpha character it encounters?
posted by edverb to Computers & Internet (14 answers total)
 
If you are using gawk, i think if you prepend your string with 0x that will force awk to handle the number as hexadecimal, which it is. then you can add one to it. When you print it out, you get it back with the 0x, so clip that off the string if you don't want it.

disclaimer: i know nothing about awk, but i mean...all these tools can convert a base-16 string to a number and print a number in base-16 right?
posted by jeb at 6:48 PM on February 5, 2009


Response by poster: Thanks Jeb for the fast reply. How would I express that?
posted by edverb at 7:06 PM on February 5, 2009


Best answer: Easy with perl:

./util | perl -lane '/WWID/ and printf "%x\n", hex($F[3]) + 1'
posted by nicwolff at 7:28 PM on February 5, 2009


Response by poster: Nicwolff, that returns

integer overflow in hexadecimal number at -e line 1, <> line 26,
ffffffff


I should specify, the search string should really be /SAS WWID/, otherwise it's possible my util will return the wrong WWID (I don't want the enclosure or the switches, for example...just my daughter card.)

Any thoughts?
posted by edverb at 8:07 PM on February 5, 2009


sounds like your number is too big for the perl number type. You might have to do something like


./util | perl -lane '/SAS WWID/ and print f "%x\n", Math::BigInt->as_hex(Math::BigInt->from_hex($F[3]) + 1)'

posted by jeb at 8:24 PM on February 5, 2009


I tried this with the stock bash and awk utils:

$ hex=500062b0000eb5a4; echo $((16#$hex+1)) | awk '{printf "%x\n", $1;}' -
ffffffff


However, when using gawk 3.1.5 (GNU awk):

$ hex=500062b0000eb5a4; echo $((16#$hex+1)) | gawk '{printf "%x\n", $1;}' -
500062b0000eb400


If you can upgrade from the stock awk to the GNU awk, I bet this will work for you.
posted by Blazecock Pileon at 9:42 PM on February 5, 2009


Never mind, that's not right, either.
posted by Blazecock Pileon at 9:42 PM on February 5, 2009


Best answer: Looks like awk runs with 32-bit precision even when compiled as 64-bit.

Anyway, here's an awk-less option:

$ hex=500062b0000eb5a4; incrementedDec=$((16#$hex+1)); echo "ibase=10;obase=16;$incrementedDec" | bc
500062B0000EB5A5

posted by Blazecock Pileon at 9:50 PM on February 5, 2009


Best answer: All this high-precision and bigint stuff might not be needed. Given you're looking at a two port problem you can probably assume that you won't roll more than one digit. Split off the last four digits to be safe, increment those, and merge back together.

./util | perl -lane '/WWID/ and printf "%s%x\n", substr($F[3],0,-4), hex(substr($F[3],-4)) + 1'

*also, fwiw, nicwolffs solution works under solaris 64bit*
posted by devbrain at 6:51 AM on February 6, 2009


@devbrain i was thinking that splitting idea too but there's a possibility of overflowing the split part, right? i mean as unlikely as it is what if the port number was 500062b0000effff ? then if you'd split off the last four digits you'd miss rolling over the 0 to a 1.
posted by jeb at 8:38 AM on February 6, 2009


@jeb: exactly -- if it WAS ffff then this would happen. Given that the application is a two port HBA (I wrote problem when I meant HBA in my first post), I've never seen one with the number of the first on the upper boundary like that.

I'd be surprised to find one with the last two digits of "f", let alone the last 4.
posted by devbrain at 12:25 PM on February 6, 2009


ahhh carry on then. i have literally no idea what a two-port hba is. seriously. i'm going to google it after this cause i'm curious.
posted by jeb at 1:28 PM on February 6, 2009


Hmm, yeah, mine only works on a 64-bit machine. Sorry 'bout that.
posted by nicwolff at 3:53 PM on February 6, 2009


Response by poster: devbrain's solution works perfectly, so that's the one I'm going with. Thanks for all of the help everyone!

jeb, here's the dual port SAS HBA (Host Bus Adapter) at issue. It is a single daughter card for blades which gives the host redundant connections to redundant SAS switches, which in turn connect to an external SAS storage enclosure (in this case, DS3200.)

Thanks again all!
posted by edverb at 6:01 PM on February 6, 2009


« Older Fun interesting things to do around Pisma Beach?   |   May my luggage never grow musty or worn... Newer »
This thread is closed to new comments.