3

How do I get the version number using sed

r-blob-1.0.2-abcsomething
urllib3-2.1.4-xyzsomething
cfile-8.0-dddsomething

How can I use "sed" to cut where there is - and [0-9], but start cutting after the - I know how to cut off the end after the version, I just don't know how to do the beginning.

The desired output should be

1.0.2
2.1.4
8.0
2

5 Answers 5

4

If the version number is known to be between the next-to-last dash and the last dash, a simple

sed 's/.*-\(.*\)-.*/\1/'

should do the trick.

2
  • I thought that . matches any character except newline, so also matches -? I think you need to capture numbers in the capture group.
    – Timo
    Commented Apr 25, 2021 at 15:27
  • 1
    No, I don't need to. Indeed the dot also matches the dash, so why does it work this way? Because the pattern requires two actual dashes. The first greedy .* makes sure that the last possible dashes are used, so if the version number is between the last dashes, we find it. Yes, you could do \([0-9.]*\) for the version number, but why not keep it simple? (-;
    – Philippos
    Commented Apr 25, 2021 at 20:14
2
$ sed -E 's/.*-([[:digit:]]+(\.[[:digit:]]+)+)-.*/\1/' file
1.0.2
2.1.4
8.0

The version number is contained between two - and consists of a positive integer ([[:digit:]]+) followed by a dot and another positive integer, at least once ((\.[[:digit:]]+)+). We match this and capture the string between the dashes. The whole line is replaced by the captured group.

Using a standard basic regular expression instead of an extended expression:

sed 's/.*-\([[:digit:]]\{1,\}\(\.[[:digit:]]\{1,\}\)\{1,\}\)-.*/\1/' file

Quick and dirty variation to grab any bit of the line between dashes that only contain digits and dots:

sed -E 's/.*-([[:digit:].]+)-.*/\1/' file
1

Get the parts between - and - with one or two dots separating the numbers:

sed -En 's/.*-([0-9]+\.)([0-9]+\.)?([0-9]+)-.*/\1\2\3/p' file

Using the -n flag and …/p only version strings of matching lines with a version number are printed. If a line doesn't contain a matching version string, then nothing is printed.

The other answers (so far) print the input line if there is no match. You didn't give an example for this case, so it's not clear how the output should look like.

1

If you don't insist on using sed, one other way is to use grep with Perl Compatible Regular Expression (PCRE) support (-P).

grep -Po '(?<=-)[0-9.]+' file

The (?<=pattern) is a lookbehind assertion. Thus we look to match a digit (0-9) or a period (.) one or more times (+) that follow a hyphen character.

1
0

Tested with below command and it worked fine

sed -e "s/.*[a-z][0-9]\?-//g" -e "s/-.*//g" filename

output

1.0.2
2.1.4
8.0

Tested with Python code

#!/usr/bin/python
import re
k=open('filename','r')
h=re.compile(r'(-([0-9]\.?){1,4})')
for i in k:
    u=re.search(h,i)
    print u.group().replace("-","")



output

 python e.py 
1.0.2
2.1.4
8.0

You must log in to answer this question.

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