I'm trying to define a regex to extract versioning information from strings that may have been formatted with different versioning schemes.
Examples:
v2.234324
4.5.0
v1.1.0-bar
v2.3-foo
V1
FEE-v1.0.2-fuu
I can "generalize" these versioning schemes by considering the following constituents:
- An optional compatibility prefix
- An optional
v
orV
- Up to 3 version components, but at least 1: major, (minor), (patch)
- An optional compatibility suffix
I'm currently using the following regex:
(?:(?<compat_prefix>^.*)-)?[vV]?(?<version>(?<major>\\d )(?:\\.(?<minor>\\d ))?(?:\\.(?<patch>\\d )?))(?:-(?<compat_suffix>.*$))?
Example:
$ echo '[{"version":"v1.2.3"},{"version":"v1.2"}]' | jq '.[].version | capture("(?:(?<compat_prefix>^.*)-)?[vV]?(?<version>(?<major>\\d )(?:\\.(?<minor>\\d ))?(?:\\.(?<patch>\\d )?))(?:-(?<compat_suffix>.*$))?")'
{
"compat_prefix": null,
"version": "1.2.3",
"major": "1",
"minor": "2",
"patch": "3",
"compat_suffix": null
}
{
"compat_prefix": null,
"version": "1.2",
"major": "1",
"minor": null,
"patch": "2",
"compat_suffix": null
}
And this works mostly fine for my purposes.
But I'd like minor
to take precedence over patch
when there are only two version components.
I've tried to use non greedy match on the patch
capture group ??
without success:
$ echo '[{"version":"foo-v1.2"}]' | jq '.[].version | capture("(?:(?<compat_prefix>^.*)-)?[vV]?(?<version>(?<major>\\d )(?:\\.(?<minor>\\d ))?(?:\\.(?<patch>\\d )??))(?:-(?<compat_suffix>.*$))?")'
{
"compat_prefix": "foo",
"version": "1.",
"major": "1",
"minor": null,
"patch": null,
"compat_suffix": null
}
I've also attempted to use possesive quantifier ?
in the minor
capturing group with similar result:
$ echo '[{"version":"foo-v1.2"}]' | jq '.[].version | capture("(?:(?<compat_prefix>^.*)-)?[vV]?(?<version>(?<major>\\d )(?:\\.(?<minor>\\d ))? (?:\\.(?<patch>\\d )?))(?:-(?<compat_suffix>.*$))?")'
# Nothing is returned
I would appreciate help to understand why my attempts aren't working and what to do instead.
CodePudding user response:
Try grouping minor
and patch
together like this:
capture("^((?<compat_prefix>.*)-)?[Vv]?(?<version>(?<major>\\d )(\\.(?<minor>\\d )(\\.(?<patch>\\d ))?)?)(-(?<compat_suffix>.*))?$")