3

I'm trying to match a version number from a string in the format 4.6, or 2.8. I have the following which I will eventually use in a function in my .bashrc file to find the OS version:

function test () {
    string="abc ABC12 123 3.4 def";
    echo `expr match "$string" '[0-9][.][0-9]'`
}

However, this doesn't match the 3.4 in the string. Can anyone point me in the right direction here?

Thanks.

7
  • can't see why it souldn't work - maybe, try using the "." as it is escaped instead of in bracets eg. [0-9]\.[0-9] Commented Aug 23, 2011 at 10:20
  • Isn't [.] any single character? Does your function match anything at all? I don't know the specifics of regex in bash, but I would assume the match would be something like "2 1". Commented Aug 23, 2011 at 10:20
  • @oliver: not if within brakets, then it's used as-is Commented Aug 23, 2011 at 10:22
  • 1
    Are you sure you understand what should happen? Seems to me that expr match STRING REGEX returns 0 if there's a match, nonzero otherwise. This is what happens with your example on my machine. Commented Aug 23, 2011 at 10:25
  • I got it working using expr match "$string" '.*([0-9][.][0-9]*)' This way it successfully prints the x.x number. Commented Aug 23, 2011 at 10:38

5 Answers 5

12

First, you can drop the echo - expr prints its result to stdout in any case.

Second, your regex needs brackets (otherwise it prints the number of characters matched, not the match itself), and it needs to begin with .*.

expr match "$string" '.*\([0-9][.][0-9]\)'

From the info expr page:

STRING : REGEX'

 Perform pattern matching.  The arguments are converted to strings
 and the second is considered to be a (basic, a la GNU `grep')
 regular expression, with a `^' implicitly prepended.  The first
 argument is then matched against this regular expression.

 If the match succeeds and REGEX uses `\(' and `\)', the `:'
 expression returns the part of STRING that matched the
 subexpression; otherwise, it returns the number of characters
 matched.
Sign up to request clarification or add additional context in comments.

Comments

7

Depending on your version of bash, there's no need to call out to expr:

$ [[ "abc ABC12 123 3.4 def" =~ [0-9][.][0-9] ]] && echo ${BASH_REMATCH[0]}
3.4

Comments

4

Thinking outside the box: if what you are looking for is determining the OS version in a script, just use uname -r or uname -v (it's POSIX). Messing with regular expression is likely to have issues as each OS may have different ways to express its version. OS vendors are so creative in inventing version jumps forward and backward, some have letters in there, and even roman numerals are not unheard of (think System V).

See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uname.html

I use in my .profile a snippet like this:

case "`uname -sr`" in
  (*BSD*)     OS=`uname -s`;;
  (SunOS\ 4*) OS=SunOS;;
  (SunOS\ 5*) OS=Solaris;;
  (IRIX\ 5*)  OS=IRIX;;
  (HP*)       OS=HP-UX;;
  (Linux*)    OS=Linux;;
  (CYGWIN*)   OS=Cygwin;;
  (*)         OS=generic
esac

Comments

3

On Mac OS X 10.6.8:

# cf. http://tldp.org/LDP/abs/html/refcards.html#AEN22429
string="abc ABC12 123 3.4 def"
expr "$string" : '.*\([0-9].[0-9]\)'    #  3.4

Comments

1
expr match "$string" '.*[0-9][.][0-9]'

2 Comments

don't know about the bash part but just the regex will match everything until (and including) 3.4
Without brackets this just prints the number of characters, too

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.