[TriLUG] detecting kernel major/minor versions

Aaron S. Joyner aaron at joyner.ws
Fri Jun 30 03:27:57 EDT 2006


Rick DeNatale wrote:

> On 6/26/06, Benjamin Reed <rangerrick at befunk.com> wrote:
>
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Joseph Mack NA3T wrote:
>>
>> > uname_r=`uname -r`
>> > minor_and_subminor=${uname_r##*2.6.}
>> > minor=${minor_and_subminor%\.*}
>>
>> Bash stuff works, although this will fail when 2.7 comes out...  <grin>
>>
>> I generally use "cut" for such things, it tends to be more future-proof:
>>
>> minor_and_subminor=`echo $uname_r | cut -d. -f3-`
>> minor=`echo $uname_r | cut -d. -f3`
>>
>> - -d. means chop up the string on the "."s
>> - -f3 means display the 3rd entry in the chopped string
>> - -f3- means display the 3rd entry and anything afterwards
>>
>> you could also do "-f3-4" to specifically ask for the 3rd through the 
>> 4th.
>
>
> Teacher! Teacher!
>
> I'm missing something here, in my case both forms of the -f parm give
> the same results:
>
> rick at bill:~$ uname -r
> 2.6.15-25-686
> rick at bill:~$ uname -r | cut -d. -f3-
> 15-25-686
> rick at bill:~$ uname -r | cut -d. -f3
> 15-25-686

When you want to match a pattern, it's hard to beat regular 
expressions.  I'll start simple:
asjoyner at bob:~$ uname -r | cut -d. -f3-
15-1-686-smp
asjoyner at bob:~$ uname -r | sed -e 's/[0-9]*\.[0-9]*\.\([0-9]*\).*/\1/'
15

This matches all occurances of 3 sets of numbers followed by dots, up 
the first thing that's not a number after the start of the 3rd set, 
takes what that defines as the 3rd set, and throws away the rest.  To 
get a better / simpler regex than this, you need to use non-greedy 
regex's, which requires a better regex engine, ala perl:
asjoyner at bob:~$ echo 200a.633\!.15-foo | sed -e 
's/[0-9]*\.[0-9]*\.\([0-9]*\).*/\1/'
200a.633!.15-foo
asjoyner at bob:~$ echo 200a.633\!.15-foo | perl -pe 
's/^.*?\..*?\.([0-9]+).*/$1/'
15

This says, take all occurances of anything up to the first dot (but no 
farther), then the same to the second dot, then grab all the following 
digits, and throw away everything but those digits.  It will parse 
things that choke and confuse the sed, such as the first version sed 
above.  I wonder if we can use negation in the character ranges to come 
up with something almost as good in sed...
asjoyner at bob:~$ echo 200a.633\!.15-foo | sed -e 
's/[^.]*\.[^.]*\.\([0-9]*\).*/\1/'
15

Yep, this regex says, take everything which is *not* a dot, up to the 
first dot, repeat to the 2nd dot, then grab the digits, and throw away 
everything else.  This is roughly equivalent to the perl expression 
above, and perhaps the most readable and simplest of all.

Ah, fun with regexs.  Can anyone come up with a pattern that looks 
remotely like a version number that the above perl or sed won't match?  
How about a better / simpler / easier-on-the-eyes pattern?

Aaron S. Joyner



More information about the TriLUG mailing list