17

I have the following:

versionNumber=$(sw_vers -productVersion) # Finds version number

versionShort=${versionNumber:0:4}  # Cut string to 1 decimal place for calculation

which works when versions are like this:

10.9.2
10.9.5

but it will not match

10.10.3

as it will return only

10.1

but I want the versionShort to be set to

10.10

I am wanting to match the major version, the first dot and the minor version as above.

4 Answers 4

17

Regexp solution:

[[ $versionNumber =~ ^[0-9]+\.[0-9]+ ]] && echo "${BASH_REMATCH[0]}"

It will always print first two numbers, for example all these:

10.5
10.5.9
10.5.8.2

Will result in 10.5 output. You can also add an else clause to check if something wrong happened (no match found).

Here is a longer version:

if [[ $versionNumber =~ ^[0-9]+\.[0-9]+ ]]; then
    versionShort=${BASH_REMATCH[0]}
else
    echo "Something is wrong with your version" >&2
fi
Sign up to request clarification or add additional context in comments.

5 Comments

how do i return the result to a variable?
@lukemh I have added a longer version that might be clearer for you. If it does not work... are you sure that you're using bash? If yes, then which version? In version 3 you have to put right side of the conditional expression into a variable.
semantic version tags must have exactly 3 numbers.
@MikeSamuel yes, that's right. Feel free to edit the answer. I wish it was easier to delete it altogether, but mentioning BASH_REMATCH is a worthy goal, even with a bad answer like this.
… or write your own, and I'll delete mine :)
15

Regexpless solution - cut off last dot and whatever follows it:

versionShort=${versionNumber%.*}

1 Comment

Careful, this doesn't work when using semver versions with a prerelease suffix like 10.9.5-rc.1
13

I had a similar question, but I needed access to all 3 segments. I did a bit of research and testing and I found this to work well

product_version=$(sw_vers -productVersion)
semver=( ${product_version//./ } )
major="${semver[0]}"
minor="${semver[1]}"
patch="${semver[2]}"
echo "${major}.${minor}.${patch}"

To answer this question directly, you could

product_version=$(sw_vers -productVersion)
semver=( ${product_version//./ } )
major="${semver[0]}"
minor="${semver[1]}"
patch="${semver[2]}"
versionShort="${major}.${minor}"

or you can use less variables

product_version=$(sw_vers -productVersion)
semver=( ${product_version//./ } )
versionShort="${semver[0]}.${semver[1]}"

2 Comments

How does "semver=( ${product_version//./ } )" work? I unfortunately get semver="10.11.6//./" when I try this.
@JasonHarrison the code works by replacing dot "." with space " ", and then taking all the arguments as a bash array. In order for it to work you need to assign the semver text to a variable first. For example, a="10.11.6"; semver=( ${a//./ } )
9

https://github.com/fsaintjacques/semver-tool https://github.com/fsaintjacques/semver-tool/blob/master/src/semver

SEMVER_REGEX="^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$"


function validate-version {
  local version=$1
  if [[ "$version" =~ $SEMVER_REGEX ]]; then
    # if a second argument is passed, store the result in var named by $2
    if [ "$#" -eq "2" ]; then
      local major=${BASH_REMATCH[1]}
      local minor=${BASH_REMATCH[2]}
      local patch=${BASH_REMATCH[3]}
      local prere=${BASH_REMATCH[4]}
      local build=${BASH_REMATCH[5]}
      eval "$2=(\"$major\" \"$minor\" \"$patch\" \"$prere\" \"$build\")"
    else
      echo "$version"
    fi
  else
    error "version $version does not match the semver scheme 'X.Y.Z(-PRERELEASE)(+BUILD)'. See help for more information."
  fi
}

1 Comment

Note: this snippet contains code that is licensed under GNU GPL v3: github.com/fsaintjacques/semver-tool/blob/master/LICENSE

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.