How to increment version number in a shell script?

前端 未结 11 2034
执念已碎
执念已碎 2020-11-29 23:47

The following simple version control script is meant to find the last version number of a given file, increment it, run a given command with the newly created file (e.g., ed

相关标签:
11条回答
  • 2020-11-30 00:18

    For just incrementing the dewey decimal version: awk -F. -v OFS=. '{$NF++;print}'

    Or in a shell script:

    NEXTVERSION=$(echo ${VERSION} | awk -F. -v OFS=. '{$NF++;print}')
    
    0 讨论(0)
  • 2020-11-30 00:25

    Pure Bash:

    increment_version ()
    {
      declare -a part=( ${1//\./ } )
      declare    new
      declare -i carry=1
    
      for (( CNTR=${#part[@]}-1; CNTR>=0; CNTR-=1 )); do
        len=${#part[CNTR]}
        new=$((part[CNTR]+carry))
        [ ${#new} -gt $len ] && carry=1 || carry=0
        [ $CNTR -gt 0 ] && part[CNTR]=${new: -len} || part[CNTR]=${new}
      done
      new="${part[*]}"
      echo -e "${new// /.}"
    } 
    
    version='1.2.3.44'
    
    increment_version $version
    

    result:

    1.2.3.45
    

    The version string is split and stored in the array part. The loop goes from the last to the first part of the version. The last part will be incremented and possibly cut down to its original length. A carry is taken to the next part.

    0 讨论(0)
  • 2020-11-30 00:26

    1. Only increment the selected part

    Usage

    increment_version 1.39.0 0 # 2.39.0
    increment_version 1.39.0 1 # 1.40.0
    increment_version 1.39.0 2 # 1.39.1
    

    Code

    ### Increments the part of the string
    ## $1: version itself
    ## $2: number of part: 0 – major, 1 – minor, 2 – patch
    increment_version() {
      local delimiter=.
      local array=($(echo "$1" | tr $delimiter '\n'))
      array[$2]=$((array[$2]+1))
      echo $(local IFS=$delimiter ; echo "${array[*]}")
    }
    

    Simplified version of @dimpiax answer


    EDIT: I created another version of this script that put zeros on the less important parts if the most important ones are changed. Just note the diferent expected results on the usage part.

    2. Increment the selected part and put zeros on the subsequent parts

    Usage

    increment_version 1.39.3 0 # 2.0.0
    increment_version 1.39.3 1 # 1.40.0
    increment_version 1.39.3 2 # 1.39.4
    
    #!/bin/bash
    
    ### Increments the part of the string
    ## $1: version itself
    ## $2: number of part: 0 – major, 1 – minor, 2 – patch
    
    increment_version() {
      local delimiter=.
      local array=($(echo "$1" | tr $delimiter '\n'))
      array[$2]=$((array[$2]+1))
      if [ $2 -lt 2 ]; then array[2]=0; fi
      if [ $2 -lt 1 ]; then array[1]=0; fi
      echo $(local IFS=$delimiter ; echo "${array[*]}")
    }
    
    0 讨论(0)
  • 2020-11-30 00:26

    Determining a version number for a software project is based on its relative change / functionality / development stage / revision. Consequent increments to the version and revision numbering is ideally a process that should be done by a human. However, not to second-guess your motivation for writing this script, here is my suggestion.

    Include some logic in your script that will do exactly what you describe in your requirement

    "...if the last section after dot has two digits, inc until 99; if only 1, then inc until 9 ... "

    Assuming the third position is the development stage number $dNum and the fourth (last) position is the revision number $rNum:

    if  [ $(expr length $rNum) = "2" ] ; then 
        if [ $rNum -lt 99 ]; then 
            rNum=$(($rNum + 1))
        else rNum=0
             dNum=$(($dNum + 1)) #some additional logic for $dNum > 9 also needed
        fi
    elif [ $(expr length $dNum) = "1" ] ; then
        ...
        ...
    fi
    

    Perhaps a function will allow the most succinct way of handling all positions (majNum.minNum.dNum.rNum).

    You will have to separate the project name and version number components of your filename in your script and then construct the version number with all its positions, and finally reconstruct the filename with something like

    new_version="$majNum.minNum.$dNum.$rNum"
    new_version_file="$old_file.$new_version"
    

    Hope that helps and check this SO discussion as well as this wikipedia entry if you want to know more about versioning conventions.

    0 讨论(0)
  • 2020-11-30 00:26

    Usage

    increment_version 1.39.0 0 # 2.39.0
    increment_version 1.39.0 1 # 1.40.0
    increment_version 1.39.0 2 # 1.39.1
    

    Code

    ### Increments the part of the string
    ## $1: version itself
    ## $2: number of part: 0 – major, 1 – minor, 2 – patch
    increment_version() {
      local delimiter=.
      local array=($(echo "$1" | tr $delimiter '\n'))
    
      for index in ${!array[@]}; do
        if [ $index -eq $2 ]; then
          local value=array[$index]
          value=$((value+1))
          array[$index]=$value
          break
        fi
      done
    
      echo $(IFS=$delimiter ; echo "${array[*]}")
    }
    
    0 讨论(0)
  • 2020-11-30 00:27

    Here is an even shorter version that also supports a postfix (nice for -SNAPSHOT)

    $ cat versions
    1.2.3.44
    1.2.3.9
    1.2.3
    9
    42.2-includes-postfix
    
    $ perl -pe 's/^((\d+\.)*)(\d+)(.*)$/$1.($3+1).$4/e' < versions
    1.2.3.45
    1.2.3.10
    1.2.4
    10
    42.3-includes-postfix
    

    Explanation

    I used regex to capture 3 parts. The stuff before the last position, the number to increment, and the stuff after.

    • ((\d+\.)*) - stuff of the from 1.1.1.1.1.
    • (\d+) - the last digit
    • (.*) - the stuff after the last digit

    I then use the e option to allow expressions in the replace part. Note with the e option \1 becomes a variable $1 and you need to concatenate variables with the dot operator.

    • $1 - the capture group of 1.1.1.1.1.
    • ($3+1) - increment the last digit. note $2 is used in the sub group of $1 to get the repeated 1.
    • $4 - the stuff after the last digit
    0 讨论(0)
提交回复
热议问题