Reputation: 2008
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
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
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
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
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
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
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 syntaxn
- 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 valuep
- only the substitution result is printed.Upvotes: 1