Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to find the best regular expression to extract a version number from a string. For example:

 echo "Version 1.2.4.1 (release mode)" | sed -ne 's/.*\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p'

The problem here is that it works only if the version number is in the format "a.b.c.d". If someone decides to add or remove a digit ("a.b.c.d.e", "a.b.c"), it will break. So I'd like to factorize the regex and tell sed that I want:

(1 or more numbers followed by a dot) x 1 or more times, followed by a number.

I can't find how to "group" the "1 or more numbers followed by a dot" so I can tell I want that pattern at least once. I've tried this but it doesn't work:

\([0-9]\+\.\)\+

Any ideas ?

share|improve this question
1  
See: A regex for version number parsing – slhck Dec 2 '11 at 13:42
up vote 3 down vote accepted

Try next 'sed' command:

$ echo "Version 1.2.4.1 (release mode)" | sed -ne 's/[^0-9]*\(\([0-9]\.\)\{0,4\}[0-9][^.]\).*/\1/p'
1.2.4.1

It uses the {i,j} syntax, which selects the expression a number of times between the first and the last number. There souldn't be any numbers in the string before the version number.

Another examples:

$ echo "Version 1.2.4.1.6 (release mode)" | sed -ne 's/[^0-9]*\(\([0-9]\.\)\{0,4\}[0-9][^.]\).*/\1/p'
1.2.4.1.6 
$ echo "Version 1.2 (release mode)" | sed -ne 's/[^0-9]*\(\([0-9]\.\)\{0,4\}[0-9][^.]\).*/\1/p'
1.2 
$ echo "Version 1.2. (release mode)" | sed -ne 's/[^0-9]*\(\([0-9]\.\)\{0,4\}[0-9][^.]\).*/\1/p'
$ 

EDIT to comments:

$ echo "Version 1.2.4.1.90 (release mode)" | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p'
share|improve this answer
    
You're specifying here the number of digits you want. What I want is that it works with any number of digits. – liberforce Dec 2 '11 at 18:01
    
I've edited the answer. I hope it works now. – Birei Dec 2 '11 at 21:33
    
I would fail on 1.2.4.10 for example, but I got the general idea, thanks. – liberforce Dec 5 '11 at 11:06
    
I finally modified a bit your last answer to work with number with several digits, and added the syntax of extended regexp that Vinicius pointed me out. This gave me: echo "Version 1.2.4.1.90 (release mode)" | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p'. Thanks to both of you for your answers ! – liberforce Dec 5 '11 at 12:18
    
I've edited the answer to show the final correct 'sed' command. Thank you. – Birei Dec 5 '11 at 16:36

Try this:

[0-9]+(\.[0-9]+)*

It means "match 1 or more digits and then match any number of (dot + digits)".

share|improve this answer
    
I've tried but you forgot to escape characters, so I tried several different combinations, but it failed even with escaping, unless I didn't find the right one. – liberforce Dec 2 '11 at 18:03
1  
You have to pass the -E flag so that the regex will be interpreted as an extended regex, like in: sed -E -e 's/[0-9]+($|\.[0-9]+)*/x/g' in.txt > out.txt – Vinicius Pinto Dec 2 '11 at 23:08
    
I'm using sed on MinGW, and it looks like -E doesn't exist on that version (sed 4.2.1). That option is renamed -r or --regexp-extended. Thanks for the tip. – liberforce Dec 5 '11 at 11:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .