Semver.sh is a library of semantic versioning functions written in pure Bash, dual licensed under the Apache License 2.0 and MIT Licenses, at your discretion. It can be safely sourced into your script or copied in piecemeal (see VENDORING in the manual).
To test, execute test.sh
. Building the full README or traditional manual page
requires mandoc(1).
Semver —
semantic versioning functions
Semver::validate validates a semantic version
string and optionally returns the parsed output. It prints its input
version, erroring with a description of
what's wrong if it's invalid. If variable is
also provided, a snippet for array assignment of the parsed parts to
variable is instead printed, allowing for an
easy eval afterwards. (You probably want to run
We can then run
Hopefully not, but if you do find some, let me know on GitHub or email me.
Semantic Versioning
specification, bash(1)
bb010g
<me@bb010g.com>
The latest sources, full contributor list, and more can be found at
https://github.com/bb010g/semver.sh.
Semver::validate | version [variable] |
Semver::compare | version version |
Semver::is_prerelease | version |
Semver::increment_major | version |
Semver::increment_minor | version |
Semver::increment_patch | version |
Semver::set_pre | version pre-release |
Semver::set_build | version build metadata |
Semver::pretty | major minor patch [pre-release] [build_metadata] |
declare -a my_var
beforehand so static
analysis tools like shellcheck(1) can work
properly.)
Semver::compare compares two semvers and returns
the result. The result is one of -1
,
meaning less than, 0
, meaning equals,
or 1
, meaning greater than. This
allows for natural use with [[ or
test(1), such as [[
$(Semver::compare a b) -ge 0 ]]
testing whether
a is greater than or equal to
b.
Semver::is_prerelease checks whether a semver is a
pre-release. The result is either yes
or no
.
Semver::increment_major,
Semver::increment_minor, and
Semver::increment_patch return a new semver with
the relevant part incremented. This does not modify
version. When incrementing, the pre-release
and build metadata parts are dropped.
Semver::set_pre and
Semver::set_build return a new semver with the
relevant part replaced. This does not modify
version. Validation is performed on
part. A part
of the empty string removes the part. Setting the pre-release does not drop
the build metadata.
Semver::pretty takes separate parts and formats
them into a semver. Note that no validation is performed on the returned
version.
If you wish to copy and paste these functions into your own script to vendor
them, Semver::validate &
Semver::pretty have no dependencies. All other
functions depend on Semver::validate. Please
remember to provide proper attribution and license information.
All errors start with the name of their associated function, like so:
Semver::validate: ...
- Semver::validate
-
invalid major: $major
|inavlid minor: $minor
|invalid patch: $patch
The part is not an integer.invalid pre-release: $pre_release
|invalid build metadata: $build_metadata
The part is not a series of non-empty identifiers ([0-9A-Za-z-]
) separated by dots (.
).
- Semver::compare
-
- All Semver::validate errors.
- Semver::increment_major | Semver::increment_minor | Semver::increment_patch
-
- All Semver::validate errors.
- Semver::set_pre | Semver::set_build
-
- All Semver::validate errors.
- Semver::set_pre:
invalid pre-release: $pre_release
| Semver::set_build:invalid build metadata: $build_metadata
The part is not a series of non-empty identifiers ([0-9A-Za-z-]
) separated by dots (.
).
#!/bin/bash
# example.sh
ver_a='1.2.11-alpha+001'
ver_b='1.4.0'
ver_invalid='1.5.'
Semver::validate "$ver_invalid" 2>/dev/null \
&& echo "$ver_invalid should be an invalid semver" \
|| echo "$ver_invalid is an invalid semver"
echo
declare -a v
eval "$(Semver::validate "$ver_a" v)"
echo "Parts of \$ver_a:"
echo "major=${v[0]}, minor=${v[1]}, patch=${v[2]},"
echo "pre-release=${v[3]}, build metadata=${v[4]}"
echo
compare_vers() {
echo -n "Comparsion between $ver_a & $ver_b: "
Semver::compare $ver_a $ver_b
}
compare_vers
ver_a=$(Semver::increment_minor "$ver_a")
ver_a=$(Semver::increment_minor "$ver_a")
compare_vers
ver_a=$(Semver::increment_patch "$ver_a")
compare_vers
ver_b=$(Semver::increment_patch "$ver_b")
ver_a=$(Semver::set_pre "$ver_a" 'alpha')
ver_b=$(Semver::set_pre "$ver_b" 'alpha')
ver_a=$(Semver::set_build "$ver_a" 'musl')
ver_b=$(Semver::set_build "$ver_b" 'glibc')
compare_vers
ver_b=$(Semver::set_pre "$ver_b" 'beta')
ver_b=$(Semver::set_build "$ver_b" '')
compare_vers
ver_a=$(Semver::set_pre "$ver_a" '')
ver_a=$(Semver::set_build "$ver_a" '')
compare_vers
echo
echo -n "Is $ver_b a pre-release? "
Semver::is_prerelease "$ver_b"
echo -n "What about $ver_a? "
Semver::is_prerelease "$ver_a"
bash example.sh
for the
following output:
1.5. is an invalid semver
Parts of $ver_a:
major=1, minor=2, patch=11,
pre-release=alpha, build metadata=001
Comparsion between 1.2.11-alpha+001 & 1.4.10: -1
Comparsion between 1.4.0 & 1.4.0: 0
Comparsion between 1.4.1 & 1.4.0: 1
Comparsion between 1.4.1-alpha+musl & 1.4.1-alpha+glibc: 0
Comparsion between 1.4.1-alpha+musl & 1.4.1-beta: -1
Comparsion between 1.4.1 & 1.4.1-beta: 1
Is 1.4.1-beta a pre-release? yes
What about 1.4.1? no
June 6, 2018 | 1.0.0 |