Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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

2 Answers 2

up vote 2 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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.