ogbofjnr
ogbofjnr

Reputation: 2008

Extract version from string cross platform

I need to create a line in makefile which will extract the version from string, and will work cross-platform, ideally without dependencies.

This is what I had

echo "golangci-lint has version 1.42.0 built..." | grep -oP '\d+\.\d+\.\d'

retuslt: 1.42.0

But it doesn't work on mac.

Trying to do it with sed like this, but doesn't work

echo "golangci-lint has version 1.42.0 built ..." | sed -n  's/.*\(\d+\.\d+\.\d\).*/\1/p'

Upvotes: 1

Views: 236

Answers (6)

dan
dan

Reputation: 5231

This awk is 100% POSIX:

awk 'match($0, /[0-9][0-9.]+[0-9]/) {print substr($0, RSTART, RLENGTH)}'

It will always print the first match and only (up to) one match per line. There can be zero or more dots in the number, but leading/trailing dots won't get printed.

grep -o is quite portable, but not every platform supported by Go has it. Eg. IBM AIX. Also note that if a line has multiple matches, it will print each match on a new line.

Upvotes: 0

Dudi Boy
Dudi Boy

Reputation: 4865

Suggesting the following:

echo "golangci-lint has version 1.42.0 built..." | grep -o '[0-9\.]\{4,\}'

Explanation

[0-9\.] --- match a single digit or dot(.)

\{4,\} --- the matched charterer 4 or more times.

Upvotes: 0

anubhava
anubhava

Reputation: 785146

-P is an experimental feature in gnu-grep which is not available on Mac BSD. However default grep available in Mac can handle it easily with -E switch but you have to use [0-9] or [[:digit:]] in place of \d in your search pattern:

s="golangci-lint has version 1.42.0 built..."
grep -Eo '([0-9]+\.)+[0-9]+' <<< "$s"

# or else
grep -Eo '([[:digit:]]+\.)+[[:digit:]]+' <<< "$s"

1.42.0

As a side note I have gnu-grep installed on my Mac using home brew package.

Upvotes: 1

glenn jackman
glenn jackman

Reputation: 246807

grep -ow '[0-9][0-9.]\+[0-9]'

That uses only a basic regular expression, and options that BSD grep and GNU grep share.

Upvotes: 3

RavinderSingh13
RavinderSingh13

Reputation: 133518

With your shown samples, you could try following awk program which will print only matched value of version out of whole line.

echo "golangci-lint has version 1.42.0 built ..." | 
awk '
{
  match($0,/[0-9]+\.[0-9]+\.[0-9]+/)
  print substr($0,RSTART,RLENGTH)
}
'

Explanation: Simple explanation would be, printing line's value with echo command of shell here and sending its output as a standard input to awk code, where using match function to match mentioned regex in it. If there is a match then printing matched value.

Explanation of regex:

[0-9]+\.[0-9]+\.[0-9]+: Matching 1 or more occurrences of digits followed by . followed by 1 or more occurrences of digits followed by another dot. followed by 1 or more digits.

Upvotes: 1

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626806

You can use

echo "golangci-lint has version 1.42.0 built ..." | sed -En  's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'

Details:

  • -E - enables the POSIX ERE syntax
  • n - default line output is suppressed now
  • .*([0-9]+\.[0-9]+\.[0-9]+).* - any text, then Group 1 capturing one or more digits, ., one or more digits, ., one or more digits and the rest of the line
  • \1 - the replacement is just Group 1 value
  • p - only the substitution result is printed.

Upvotes: 1

Related Questions