Làm thế nào để so sánh hai chuỗi trong định dạng phiên bản phân tách dấu chấm trong Bash?


176

Có cách nào để so sánh chuỗi như trên bash, ví dụ: 2.4.52.82.4.5.1?


4
Không, đừng làm điều đó với bc. Đó là văn bản không phải là số. 2.1 < 2.10sẽ thất bại theo cách này.
viraptor

Câu trả lời:


200

Đây là phiên bản Bash thuần túy không yêu cầu bất kỳ tiện ích bên ngoài nào:

#!/bin/bash
vercomp () {
    if [[ $1 == $2 ]]
    then
        return 0
    fi
    local IFS=.
    local i ver1=($1) ver2=($2)
    # fill empty fields in ver1 with zeros
    for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
    do
        ver1[i]=0
    done
    for ((i=0; i<${#ver1[@]}; i++))
    do
        if [[ -z ${ver2[i]} ]]
        then
            # fill empty fields in ver2 with zeros
            ver2[i]=0
        fi
        if ((10#${ver1[i]} > 10#${ver2[i]}))
        then
            return 1
        fi
        if ((10#${ver1[i]} < 10#${ver2[i]}))
        then
            return 2
        fi
    done
    return 0
}

testvercomp () {
    vercomp $1 $2
    case $? in
        0) op='=';;
        1) op='>';;
        2) op='<';;
    esac
    if [[ $op != $3 ]]
    then
        echo "FAIL: Expected '$3', Actual '$op', Arg1 '$1', Arg2 '$2'"
    else
        echo "Pass: '$1 $op $2'"
    fi
}

# Run tests
# argument table format:
# testarg1   testarg2     expected_relationship
echo "The following tests should pass"
while read -r test
do
    testvercomp $test
done << EOF
1            1            =
2.1          2.2          <
3.0.4.10     3.0.4.2      >
4.08         4.08.01      <
3.2.1.9.8144 3.2          >
3.2          3.2.1.9.8144 <
1.2          2.1          <
2.1          1.2          >
5.6.7        5.6.7        =
1.01.1       1.1.1        =
1.1.1        1.01.1       =
1            1.0          =
1.0          1            =
1.0.2.0      1.0.2        =
1..0         1.0          =
1.0          1..0         =
EOF

echo "The following test should fail (test the tester)"
testvercomp 1 1 '>'

Chạy thử nghiệm:

$ . ./vercomp
The following tests should pass
Pass: '1 = 1'
Pass: '2.1 < 2.2'
Pass: '3.0.4.10 > 3.0.4.2'
Pass: '4.08 < 4.08.01'
Pass: '3.2.1.9.8144 > 3.2'
Pass: '3.2 < 3.2.1.9.8144'
Pass: '1.2 < 2.1'
Pass: '2.1 > 1.2'
Pass: '5.6.7 = 5.6.7'
Pass: '1.01.1 = 1.1.1'
Pass: '1.1.1 = 1.01.1'
Pass: '1 = 1.0'
Pass: '1.0 = 1'
Pass: '1.0.2.0 = 1.0.2'
Pass: '1..0 = 1.0'
Pass: '1.0 = 1..0'
The following test should fail (test the tester)
FAIL: Expected '>', Actual '=', Arg1 '1', Arg2 '1'

2
Bạn có thể nói rõ giấy phép của đoạn mã này không? Mã trông hoàn hảo nhưng tôi không chắc mình có thể sử dụng nó trong dự án được cấp phép AGPLv3 hay không.
Kamil Dziedzic

4
@KamilDziedzic: Các điều khoản cấp phép được nêu ở cuối trang này (và hầu hết các điều khoản khác).
Tạm dừng cho đến khi có thông báo mới.

4
gnu.org/licenses/license-list.html#ccbysa Please don't use it for software or documentation, since it is incompatible with the GNU GPL : / nhưng +1 cho mã tuyệt vời
Kamil Dziedzic

3
điều này không thành công '1.4rc2> 1.3.3'. chú ý phiên bản chữ và số
Salimane Adjao Moustapha

1
@SalimaneAdjaoMoustapha: Nó không được thiết kế để xử lý loại chuỗi phiên bản đó. Tôi không thấy bất kỳ câu trả lời nào khác ở đây có thể xử lý sự so sánh đó.
Tạm dừng cho đến khi có thông báo mới.

139

Nếu bạn có coreutils-7 (trong Ubuntu Karmic nhưng không phải Jasyy) thì sortlệnh của bạn sẽ có một -Vtùy chọn (sắp xếp phiên bản) mà bạn có thể sử dụng để so sánh:

verlte() {
    [  "$1" = "`echo -e "$1\n$2" | sort -V | head -n1`" ]
}

verlt() {
    [ "$1" = "$2" ] && return 1 || verlte $1 $2
}

verlte 2.5.7 2.5.6 && echo "yes" || echo "no" # no
verlt 2.4.10 2.4.9 && echo "yes" || echo "no" # no
verlt 2.4.8 2.4.10 && echo "yes" || echo "no" # yes
verlte 2.5.6 2.5.6 && echo "yes" || echo "no" # yes
verlt 2.5.6 2.5.6 && echo "yes" || echo "no" # no

5
Giải pháp tốt đẹp. Đối với người dùng Mac OSX, bạn có thể sử dụng GNU Coreutils gsort. Điều đó có sẵn thông qua homebrew : brew install coreutils. Sau đó, nên sửa đổi ở trên để sử dụng gsort.
justsee

Tôi đã làm cho nó hoạt động trong một tập lệnh trong Ubuntu chính xác bằng cách loại bỏ -e khỏi echo.
Hannes R.

2
Không hoạt động với ví dụ Busybox trên hệ thống nhúng Linux, vì Busyboxsort không có -Vtùy chọn.
Craig McQueen

3
Tốt hơn là sử dụng printfthay vì echo -e.
phk

4
GNU sortcũng có -Choặc --check=silent, vì vậy bạn có thể viết verlte() { printf '%s\n%s' "$1" "$2" | sort -C -V }; và kiểm tra nghiêm ngặt ít hơn là đơn giản hơn được thực hiện như verlt() { ! verlte "$2" "$1" }.
Toby Speight

60

Có lẽ không có cách chính xác nào để đạt được điều này. Nếu bạn đang cố so sánh các phiên bản trong hệ thống gói Debian, hãy thửdpkg --compare-versions <first> <relation> <second>.


8
Cách sử dụng: dpkg --compare-versions "1.0" "lt" "1.2"có nghĩa là 1.0 nhỏ hơn 1.2. Kết quả so sánh $?0nếu đúng để bạn có thể sử dụng nó trực tiếp sau ifcâu lệnh.
KrisWebDev

48

GNU sort có một tùy chọn cho nó:

printf '2.4.5\n2.8\n2.4.5.1\n' | sort -V

cho:

2.4.5
2.4.5.1
2.8

2
Câu hỏi dường như là về sắp xếp phiên bản. Hãy xem xét:echo -e "2.4.10\n2.4.9" | sort -n -t.
kanaka

2
sắp xếp số này là không đúng. Bạn sẽ cần ít nhất là bình thường hóa các chuỗi đầu tiên.
frankc

3
Không hoạt động với ví dụ Busybox trên hệ thống nhúng Linux, vì Busyboxsort không có -Vtùy chọn.
Craig McQueen

Điều đáng chú ý là nếu số phiên bản có thể là bất cứ thứ gì thì tốt hơn nên sử dụng nó trong biểu mẫu printf '%s\n' "2.4.5" "2.8" "2.4.5.1" | sort -V.
phk

Như đã lưu ý trong một câu trả lời khác , điều này chỉ hoạt động với coreutils 7+.
ivan_pozdeev

35

Chà nếu bạn biết số lượng trường bạn có thể sử dụng -kn, n và nhận được một giải pháp siêu đơn giản

echo '2.4.5
2.8
2.4.5.1
2.10.2' | sort -t '.' -k 1,1 -k 2,2 -k 3,3 -k 4,4 -g

2.4.5
2.4.5.1
2.8
2.10.2

4
bốn năm đến dự tiệc muộn, nhưng giải pháp yêu thích của tôi cho đến nay :)
LOAS 11/03/2015

vâng, -ttùy chọn chỉ chấp nhận các tab ký tự đơn ... nếu không, 2.4-r9cũng sẽ hoạt động. Thật là xấu hổ: /
scottysseus 7/07/2015

1
Đối với compat Solaris, tôi phải đổi -gsang -n. Bất kỳ lý do tại sao không cho ví dụ này? Trên một ghi chú bên cạnh ... để thực hiện so sánh loại "lớn hơn", bạn có thể kiểm tra xem loại sắp xếp mong muốn có giống với loại thực tế không ... ví dụ desired="1.9\n1.11"; actual="$(echo -e $desired |sort -t '.' -k 1,1 -k 2,2 -g)";và sau đó xác minh if [ "$desired" = "$actual" ].
tresf

23

Điều này là cho tối đa 4 lĩnh vực trong phiên bản.

$ function ver { printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' ' '); }
$ [ $(ver 10.9) -lt $(ver 10.10) ] && echo hello  
hello

3
Trong trường hợp phiên bản cũng có thể có 5 trường, các trường hợp trên có thể được thực hiện an toàn như thế này:printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' '\n' | head -n 4)
cướp

2
Không chắc chắn nếu tất cả áp dụng cho tất cả các phiên bản bash, nhưng trong trường hợp của tôi, một dấu chấm phẩy bị thiếu sau dấu ngoặc tròn cuối cùng.
Holger Brandl

1
@robinst Để head -nlàm việc, tôi phải đổi sangtr '.' '\n'
Victor Sergienko

Đã thêm dấu chấm phẩy.
codeforester

1
@OleksiiChekulaiev trĐầu ra ống thông qua sed 's/\(^\| \)0\([0-9][0-9]*\)/\1\2/g'đó sẽ đảm nhiệm việc đó (Khá vụng về)
Otheus

21
function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }

Được sử dụng như vậy:

if [ $(version $VAR) -ge $(version "6.2.0") ]; then
    echo "Version is up to date"
fi

(từ https://apple.stackexchange.com/a/123408/11374 )


2
Điều này là tốt hơn nhiều so với chỉ sử dụng bash printf mặc định như đề xuất ở trên. Nó xử lý chính xác các phiên bản như "1.09" mà printf thông thường không thể xử lý vì "09 không phải là số chính xác". Nó cũng tự động loại bỏ các số 0 đứng đầu, điều này rất tốt vì đôi khi các số 0 hàng đầu có thể dẫn đến các lỗi so sánh.
Oleksii Chekulaiev

8

Bạn có thể phân chia đệ quy .và so sánh như được hiển thị trong thuật toán sau, được lấy từ đây . Nó trả về 10 nếu các phiên bản giống nhau, 11 nếu phiên bản 1 lớn hơn phiên bản 2 và 9 nếu không.

#!/bin/bash
do_version_check() {

   [ "$1" == "$2" ] && return 10

   ver1front=`echo $1 | cut -d "." -f -1`
   ver1back=`echo $1 | cut -d "." -f 2-`

   ver2front=`echo $2 | cut -d "." -f -1`
   ver2back=`echo $2 | cut -d "." -f 2-`

   if [ "$ver1front" != "$1" ] || [ "$ver2front" != "$2" ]; then
       [ "$ver1front" -gt "$ver2front" ] && return 11
       [ "$ver1front" -lt "$ver2front" ] && return 9

       [ "$ver1front" == "$1" ] || [ -z "$ver1back" ] && ver1back=0
       [ "$ver2front" == "$2" ] || [ -z "$ver2back" ] && ver2back=0
       do_version_check "$ver1back" "$ver2back"
       return $?
   else
           [ "$1" -gt "$2" ] && return 11 || return 9
   fi
}    

do_version_check "$1" "$2"

Nguồn


6

nếu chỉ cần biết liệu một phiên bản có thấp hơn phiên bản khác hay không thì tôi đã kiểm tra xem liệu có sort --version-sortthay đổi thứ tự của chuỗi phiên bản của tôi không:

    string="$1
$2"
    [ "$string" == "$(sort --version-sort <<< "$string")" ]

5

Tôi đã triển khai một hàm trả về kết quả giống như của Dennis Williamson nhưng sử dụng ít dòng hơn. Nó thực hiện một kiểm tra sự tỉnh táo ban đầu gây ra 1..0thất bại từ các bài kiểm tra của mình (mà tôi sẽ tranh luận nên là trường hợp) nhưng tất cả các xét nghiệm khác của ông vượt qua với mã này:

#!/bin/bash
version_compare() {
    if [[ $1 =~ ^([0-9]+\.?)+$ && $2 =~ ^([0-9]+\.?)+$ ]]; then
        local l=(${1//./ }) r=(${2//./ }) s=${#l[@]}; [[ ${#r[@]} -gt ${#l[@]} ]] && s=${#r[@]}

        for i in $(seq 0 $((s - 1))); do
            [[ ${l[$i]} -gt ${r[$i]} ]] && return 1
            [[ ${l[$i]} -lt ${r[$i]} ]] && return 2
        done

        return 0
    else
        echo "Invalid version number given"
        exit 1
    fi
}

Nó không hoạt động ... Nó nghĩ rằng 1.15 nhỏ hơn 1.8.1.
Carlo Wood

5

Đây là một hàm Bash đơn giản không sử dụng các lệnh bên ngoài. Nó hoạt động cho các chuỗi phiên bản có tối đa ba phần số trong đó - ít hơn 3 cũng tốt. Nó có thể dễ dàng được mở rộng để biết thêm. Nó cụ =, <, <=, >, >=, và !=điều kiện.

#!/bin/bash
vercmp() {
    version1=$1 version2=$2 condition=$3

    IFS=. v1_array=($version1) v2_array=($version2)
    v1=$((v1_array[0] * 100 + v1_array[1] * 10 + v1_array[2]))
    v2=$((v2_array[0] * 100 + v2_array[1] * 10 + v2_array[2]))
    diff=$((v2 - v1))
    [[ $condition = '='  ]] && ((diff == 0)) && return 0
    [[ $condition = '!=' ]] && ((diff != 0)) && return 0
    [[ $condition = '<'  ]] && ((diff >  0)) && return 0
    [[ $condition = '<=' ]] && ((diff >= 0)) && return 0
    [[ $condition = '>'  ]] && ((diff <  0)) && return 0
    [[ $condition = '>=' ]] && ((diff <= 0)) && return 0
    return 1
}

Đây là bài kiểm tra:

for tv1 in '*' 1.1.1 2.5.3 7.3.0 0.5.7 10.3.9 8.55.32 0.0.1; do
    for tv2 in 3.1.1 1.5.3 4.3.0 0.0.7 0.3.9 11.55.32 10.0.0 '*'; do
      for c in '=' '>' '<' '>=' '<=' '!='; do
        vercmp "$tv1" "$tv2" "$c" && printf '%s\n' "$tv1 $c $tv2 is true" || printf '%s\n' "$tv1 $c $tv2 is false"
      done
    done
done

Một tập hợp con của đầu ra thử nghiệm:

<snip>

* >= * is true
* <= * is true
* != * is true
1.1.1 = 3.1.1 is false
1.1.1 > 3.1.1 is false
1.1.1 < 3.1.1 is true
1.1.1 >= 3.1.1 is false
1.1.1 <= 3.1.1 is true
1.1.1 != 3.1.1 is true
1.1.1 = 1.5.3 is false
1.1.1 > 1.5.3 is false
1.1.1 < 1.5.3 is true
1.1.1 >= 1.5.3 is false
1.1.1 <= 1.5.3 is true
1.1.1 != 1.5.3 is true
1.1.1 = 4.3.0 is false
1.1.1 > 4.3.0 is false

<snip>

5
  • Chức năng V - giải pháp bash thuần túy, không cần các tiện ích bên ngoài.
  • Hỗ trợ = == != < <= >>= (từ điển).
  • Tùy chọn so sánh đuôi thư: 1.5a < 1.5b
  • So sánh độ dài không bằng nhau: 1.6 > 1.5b
  • Đọc từ trái sang phải : if V 1.5 '<' 1.6; then ....

<>

# Sample output
# Note: ++ (true) and __ (false) mean that V works correctly.

++ 3.6 '>' 3.5b
__ 2.5.7 '<=' 2.5.6
++ 2.4.10 '<' 2.5.9
__ 3.0002 '>' 3.0003.3
++ 4.0-RC2 '>' 4.0-RC1

<>

function V() # $1-a $2-op $3-$b
# Compare a and b as version strings. Rules:
# R1: a and b : dot-separated sequence of items. Items are numeric. The last item can optionally end with letters, i.e., 2.5 or 2.5a.
# R2: Zeros are automatically inserted to compare the same number of items, i.e., 1.0 < 1.0.1 means 1.0.0 < 1.0.1 => yes.
# R3: op can be '=' '==' '!=' '<' '<=' '>' '>=' (lexicographic).
# R4: Unrestricted number of digits of any item, i.e., 3.0003 > 3.0000004.
# R5: Unrestricted number of items.
{
  local a=$1 op=$2 b=$3 al=${1##*.} bl=${3##*.}
  while [[ $al =~ ^[[:digit:]] ]]; do al=${al:1}; done
  while [[ $bl =~ ^[[:digit:]] ]]; do bl=${bl:1}; done
  local ai=${a%$al} bi=${b%$bl}

  local ap=${ai//[[:digit:]]} bp=${bi//[[:digit:]]}
  ap=${ap//./.0} bp=${bp//./.0}

  local w=1 fmt=$a.$b x IFS=.
  for x in $fmt; do [ ${#x} -gt $w ] && w=${#x}; done
  fmt=${*//[^.]}; fmt=${fmt//./%${w}s}
  printf -v a $fmt $ai$bp; printf -v a "%s-%${w}s" $a $al
  printf -v b $fmt $bi$ap; printf -v b "%s-%${w}s" $b $bl

  case $op in
    '<='|'>=' ) [ "$a" ${op:0:1} "$b" ] || [ "$a" = "$b" ] ;;
    * )         [ "$a" $op "$b" ] ;;
  esac
}

Mã giải thích

Dòng 1 : Xác định các biến cục bộ:

  • a, op, b- toán hạng so sánh và điều hành, ví dụ, "3.6"> "3.5a".
  • al, bl- đuôi chữ cái ab, được khởi tạo cho mục đuôi, nghĩa là "6" và "5a".

Dòng 2, 3 : Các chữ số cắt trái từ các mục đuôi để chỉ còn lại các chữ cái, nếu có, nghĩa là "" và "a".

Dòng 4 : Cắt các chữ cái bên phải từ abchỉ để lại chuỗi các mục số là biến cục bộ aibi , tức là "3.6" và "3.5". Ví dụ đáng chú ý: "4.01-RC2"> "4.01-RC1" mang lại ai = "4.01" al = "- RC2" và bi = "4.01" bl = "- RC1".

Dòng 6 : Xác định các biến cục bộ:

  • ap, bp- không có miếng đệm bên phải cho aibi. Bắt đầu bằng cách chỉ giữ lại các dấu chấm liên mục, trong đó số lượng bằng số phần tử của abtương ứng.

Dòng 7 : Sau đó nối "0" sau mỗi dấu chấm để tạo mặt nạ đệm.

Dòng 9 : Biến cục bộ:

  • w - chiều rộng mục
  • fmt - chuỗi định dạng printf, sẽ được tính
  • x - tạm thời
  • Với IFS=.bash chia các giá trị biến tại '.'.

Dòng 10 : Tính toán w, chiều rộng mục tối đa, sẽ được sử dụng để căn chỉnh các mục để so sánh từ điển. Trong ví dụ của chúng tôi w = 2.

Dòng 11 : Tạo định dạng căn chỉnh printf bằng cách thay thế từng ký tự $a.$bbằng %${w}s, ví dụ: "3.6"> "3.5a" mang lại "% 2s% 2s% 2s% 2s".

Dòng 12 : "printf -v a" đặt giá trị của biến a. Điều này tương đương với a=sprintf(...)trong nhiều ngôn ngữ lập trình. Lưu ý rằng ở đây, do ảnh hưởng của IFS =. các đối số để printfphân chia thành các mục riêng lẻ.

Với các printfmục đầu tiên ađược đệm trái với khoảng trắng trong khi các mục "0" đủ được thêm vào bpđể đảm bảo rằng chuỗi kết quả acó thể được so sánh một cách có ý nghĩa với một định dạng tương tự b.

Lưu ý rằng chúng tôi nối thêm bp- không apphải aiapbpcó thể có chiều dài khác nhau, do đó, điều này dẫn đến abcó độ dài bằng nhau.

Với thứ hai printfchúng tôi thêm phần thư alđến avới đủ đệm để cho phép so sánh có ý nghĩa. Bây giờ ađã sẵn sàng để so sánh với b.

Dòng 13 : Tương tự như dòng 12 nhưng cho b.

Dòng 15 : Phân tách các trường hợp so sánh giữa các toán tử không tích hợp ( <=>=) và các toán tử tích hợp.

Dòng 16 : Nếu toán tử so sánh <=thì kiểm tra a<b or a=b- tương ứng>= a<b or a=b

Dòng 17 : Kiểm tra các toán tử so sánh tích hợp.

<>

# All tests

function P { printf "$@"; }
function EXPECT { printf "$@"; }
function CODE { awk $BASH_LINENO'==NR{print " "$2,$3,$4}' "$0"; }
P 'Note: ++ (true) and __ (false) mean that V works correctly.\n'

V 2.5    '!='  2.5      && P + || P _; EXPECT _; CODE
V 2.5    '='   2.5      && P + || P _; EXPECT +; CODE
V 2.5    '=='  2.5      && P + || P _; EXPECT +; CODE

V 2.5a   '=='  2.5b     && P + || P _; EXPECT _; CODE
V 2.5a   '<'   2.5b     && P + || P _; EXPECT +; CODE
V 2.5a   '>'   2.5b     && P + || P _; EXPECT _; CODE
V 2.5b   '>'   2.5a     && P + || P _; EXPECT +; CODE
V 2.5b   '<'   2.5a     && P + || P _; EXPECT _; CODE
V 3.5    '<'   3.5b     && P + || P _; EXPECT +; CODE
V 3.5    '>'   3.5b     && P + || P _; EXPECT _; CODE
V 3.5b   '>'   3.5      && P + || P _; EXPECT +; CODE
V 3.5b   '<'   3.5      && P + || P _; EXPECT _; CODE
V 3.6    '<'   3.5b     && P + || P _; EXPECT _; CODE
V 3.6    '>'   3.5b     && P + || P _; EXPECT +; CODE
V 3.5b   '<'   3.6      && P + || P _; EXPECT +; CODE
V 3.5b   '>'   3.6      && P + || P _; EXPECT _; CODE

V 2.5.7  '<='  2.5.6    && P + || P _; EXPECT _; CODE
V 2.4.10 '<'   2.4.9    && P + || P _; EXPECT _; CODE
V 2.4.10 '<'   2.5.9    && P + || P _; EXPECT +; CODE
V 3.4.10 '<'   2.5.9    && P + || P _; EXPECT _; CODE
V 2.4.8  '>'   2.4.10   && P + || P _; EXPECT _; CODE
V 2.5.6  '<='  2.5.6    && P + || P _; EXPECT +; CODE
V 2.5.6  '>='  2.5.6    && P + || P _; EXPECT +; CODE
V 3.0    '<'   3.0.3    && P + || P _; EXPECT +; CODE
V 3.0002 '<'   3.0003.3 && P + || P _; EXPECT +; CODE
V 3.0002 '>'   3.0003.3 && P + || P _; EXPECT _; CODE
V 3.0003.3 '<' 3.0002   && P + || P _; EXPECT _; CODE
V 3.0003.3 '>' 3.0002   && P + || P _; EXPECT +; CODE

V 4.0-RC2 '>' 4.0-RC1   && P + || P _; EXPECT +; CODE
V 4.0-RC2 '<' 4.0-RC1   && P + || P _; EXPECT _; CODE

4

Tôi đang sử dụng Linux nhúng (Yocto) với BusyBox. BusyBoxsort không có -Vtùy chọn (nhưng BusyBoxexpr match có thể thực hiện các biểu thức thông thường). Vì vậy, tôi cần một phiên bản Bash so sánh làm việc với ràng buộc đó.

Tôi đã thực hiện như sau (tương tự như câu trả lời của Dennis Williamson ) để so sánh bằng cách sử dụng loại thuật toán "sắp xếp tự nhiên". Nó chia chuỗi thành các phần số và phần không số; nó so sánh các phần số bằng số (vì vậy 10lớn hơn 9) và so sánh các phần không phải là số so sánh ASCII đơn giản.

ascii_frag() {
    expr match "$1" "\([^[:digit:]]*\)"
}

ascii_remainder() {
    expr match "$1" "[^[:digit:]]*\(.*\)"
}

numeric_frag() {
    expr match "$1" "\([[:digit:]]*\)"
}

numeric_remainder() {
    expr match "$1" "[[:digit:]]*\(.*\)"
}

vercomp_debug() {
    OUT="$1"
    #echo "${OUT}"
}

# return 1 for $1 > $2
# return 2 for $1 < $2
# return 0 for equal
vercomp() {
    local WORK1="$1"
    local WORK2="$2"
    local NUM1="", NUM2="", ASCII1="", ASCII2=""
    while true; do
        vercomp_debug "ASCII compare"
        ASCII1=`ascii_frag "${WORK1}"`
        ASCII2=`ascii_frag "${WORK2}"`
        WORK1=`ascii_remainder "${WORK1}"`
        WORK2=`ascii_remainder "${WORK2}"`
        vercomp_debug "\"${ASCII1}\" remainder \"${WORK1}\""
        vercomp_debug "\"${ASCII2}\" remainder \"${WORK2}\""

        if [ "${ASCII1}" \> "${ASCII2}" ]; then
            vercomp_debug "ascii ${ASCII1} > ${ASCII2}"
            return 1
        elif [ "${ASCII1}" \< "${ASCII2}" ]; then
            vercomp_debug "ascii ${ASCII1} < ${ASCII2}"
            return 2
        fi
        vercomp_debug "--------"

        vercomp_debug "Numeric compare"
        NUM1=`numeric_frag "${WORK1}"`
        NUM2=`numeric_frag "${WORK2}"`
        WORK1=`numeric_remainder "${WORK1}"`
        WORK2=`numeric_remainder "${WORK2}"`
        vercomp_debug "\"${NUM1}\" remainder \"${WORK1}\""
        vercomp_debug "\"${NUM2}\" remainder \"${WORK2}\""

        if [ -z "${NUM1}" -a -z "${NUM2}" ]; then
            vercomp_debug "blank 1 and blank 2 equal"
            return 0
        elif [ -z "${NUM1}" -a -n "${NUM2}" ]; then
            vercomp_debug "blank 1 less than non-blank 2"
            return 2
        elif [ -n "${NUM1}" -a -z "${NUM2}" ]; then
            vercomp_debug "non-blank 1 greater than blank 2"
            return 1
        fi

        if [ "${NUM1}" -gt "${NUM2}" ]; then
            vercomp_debug "num ${NUM1} > ${NUM2}"
            return 1
        elif [ "${NUM1}" -lt "${NUM2}" ]; then
            vercomp_debug "num ${NUM1} < ${NUM2}"
            return 2
        fi
        vercomp_debug "--------"
    done
}

Nó có thể so sánh các số phiên bản phức tạp hơn như

  • 1.2-r3 đấu với 1.2-r4
  • 1.2rc3 đấu với 1.2r4

Lưu ý rằng nó không trả lại kết quả tương tự cho một số trường hợp góc trong câu trả lời của Dennis Williamson . Đặc biệt:

1            1.0          <
1.0          1            >
1.0.2.0      1.0.2        >
1..0         1.0          >
1.0          1..0         <

Nhưng đó là những trường hợp góc, và tôi nghĩ rằng kết quả vẫn hợp lý.


4
$ for OVFTOOL_VERSION in "4.2.0" "4.2.1" "5.2.0" "3.2.0" "4.1.9" "4.0.1" "4.3.0" "4.5.0" "4.2.1" "30.1.0" "4" "5" "4.1" "4.3"
> do
>   if [ $(echo "$OVFTOOL_VERSION 4.2.0" | tr " " "\n" | sort --version-sort | head -n 1) = 4.2.0 ]; then 
>     echo "$OVFTOOL_VERSION is >= 4.2.0"; 
>   else 
>     echo "$OVFTOOL_VERSION is < 4.2.0"; 
>   fi
> done
4.2.0 is >= 4.2.0
4.2.1 is >= 4.2.0
5.2.0 is >= 4.2.0
3.2.0 is < 4.2.0
4.1.9 is < 4.2.0
4.0.1 is < 4.2.0
4.3.0 is >= 4.2.0
4.5.0 is >= 4.2.0
4.2.1 is >= 4.2.0
30.1.0 is >= 4.2.0
4 is < 4.2.0
5 is >= 4.2.0
4.1 is < 4.2.0
4.3 is >= 4.2.0

1
Với GNU sort, bạn có thể sử dụng --check=silent, không cần test, như thế này: if printf '%s\n%s' 4.2.0 "$OVFTOOL_VERSION" | sort --version-sort -C
Toby Speight

Cảm ơn bạn @Toby Speight
djna

4

Đây cũng là một pure bashgiải pháp, vì printf là một bash dựng sẵn.

function ver()
# Description: use for comparisons of version strings.
# $1  : a version string of form 1.2.3.4
# use: (( $(ver 1.2.3.4) >= $(ver 1.2.3.3) )) && echo "yes" || echo "no"
{
    printf "%02d%02d%02d%02d" ${1//./ }
}

Giới hạn ... Chỉ hoạt động đối với số thuần dưới 100 với đúng 4 giá trị. Cố gắng nhé!
anthony

2

Đối với phiên bản cũ / busybox sort. Hình thức đơn giản cung cấp kết quả đại khái và thường làm việc.

sort -n

Điều này đặc biệt hữu ích trên phiên bản có chứa các ký hiệu alpha như

10.c.3
10.a.4
2.b.5

1

Còn cái này thì sao? Có vẻ để làm việc?

checkVersion() {
subVer1=$1
subVer2=$2

[ "$subVer1" == "$subVer2" ] && echo "Version is same"
echo "Version 1 is $subVer1"
testVer1=$subVer1
echo "Test version 1 is $testVer1"
x=0
while [[ $testVer1 != "" ]]
do
  ((x++))
  testVer1=`echo $subVer1|cut -d "." -f $x`
  echo "testVer1 now is $testVer1"
  testVer2=`echo $subVer2|cut -d "." -f $x`
  echo "testVer2 now is $testVer2"
  if [[ $testVer1 -gt $testVer2 ]]
  then
    echo "$ver1 is greater than $ver2"
    break
  elif [[ "$testVer2" -gt "$testVer1" ]]
  then
    echo "$ver2 is greater than $ver1"
    break
  fi
  echo "This is the sub verion for first value $testVer1"
  echo "This is the sub verion for second value $testVer2"
done
}

ver1=$1
ver2=$2
checkVersion "$ver1" "$ver2"

1

Đây là một giải pháp bash thuần túy khác mà không có bất kỳ cuộc gọi bên ngoài nào:

#!/bin/bash

function version_compare {

IFS='.' read -ra ver1 <<< "$1"
IFS='.' read -ra ver2 <<< "$2"

[[ ${#ver1[@]} -gt ${#ver2[@]} ]] && till=${#ver1[@]} || till=${#ver2[@]}

for ((i=0; i<${till}; i++)); do

    local num1; local num2;

    [[ -z ${ver1[i]} ]] && num1=0 || num1=${ver1[i]}
    [[ -z ${ver2[i]} ]] && num2=0 || num2=${ver2[i]}

    if [[ $num1 -gt $num2 ]]; then
        echo ">"; return 0
    elif
       [[ $num1 -lt $num2 ]]; then
        echo "<"; return 0
    fi
done

echo "="; return 0
}

echo "${1} $(version_compare "${1}" "${2}") ${2}"

Và thậm chí còn có giải pháp đơn giản hơn, nếu bạn chắc chắn rằng các phiên bản được đề cập không chứa các số 0 đứng đầu sau dấu chấm đầu tiên:

#!/bin/bash

function version_compare {

local ver1=${1//.}
local ver2=${2//.}


    if [[ $ver1 -gt $ver2 ]]; then
        echo ">"; return 0
    elif    
       [[ $ver1 -lt $ver2 ]]; then
        echo "<"; return 0
    fi 

echo "="; return 0
}

echo "${1} $(version_compare "${1}" "${2}") ${2}"

Điều này sẽ hoạt động cho một cái gì đó như 1.2.3 so với 1.3.1 so với 0.9.7, nhưng sẽ không hoạt động với 1.2.3 so với 1.2.3.0 hoặc 1.01.1 so với 1.1.1


Phiên bản thứ hai có thể dẫn đến4.4.4 > 44.3
yairchu

1

Đây là một sàng lọc của câu trả lời hàng đầu (Dennis) ngắn gọn hơn và sử dụng lược đồ giá trị trả về khác nhau để giúp dễ dàng thực hiện <= và> = với một so sánh duy nhất. Nó cũng so sánh mọi thứ sau ký tự đầu tiên không có trong [0-9.] Theo từ vựng, vì vậy 1.0rc1 <1.0rc2.

# Compares two tuple-based, dot-delimited version numbers a and b (possibly
# with arbitrary string suffixes). Returns:
# 1 if a<b
# 2 if equal
# 3 if a>b
# Everything after the first character not in [0-9.] is compared
# lexicographically using ASCII ordering if the tuple-based versions are equal.
compare-versions() {
    if [[ $1 == $2 ]]; then
        return 2
    fi
    local IFS=.
    local i a=(${1%%[^0-9.]*}) b=(${2%%[^0-9.]*})
    local arem=${1#${1%%[^0-9.]*}} brem=${2#${2%%[^0-9.]*}}
    for ((i=0; i<${#a[@]} || i<${#b[@]}; i++)); do
        if ((10#${a[i]:-0} < 10#${b[i]:-0})); then
            return 1
        elif ((10#${a[i]:-0} > 10#${b[i]:-0})); then
            return 3
        fi
    done
    if [ "$arem" '<' "$brem" ]; then
        return 1
    elif [ "$arem" '>' "$brem" ]; then
        return 3
    fi
    return 2
}

Đây là một upvote vì nó đang được sử dụng ở đây
Codebling

1

Tôi đã thực hiện một chức năng so sánh khác. Điều này có hai yêu cầu cụ thể: (i) Tôi không muốn chức năng bị lỗi bằng cách sử dụng return 1echothay vào đó; (ii) khi chúng tôi truy xuất các phiên bản từ phiên bản kho lưu trữ git "1.0" phải lớn hơn "1.0.2", nghĩa là "1.0" xuất phát từ trung kế.

function version_compare {
  IFS="." read -a v_a <<< "$1"
  IFS="." read -a v_b <<< "$2"

  while [[ -n "$v_a" || -n "$v_b" ]]; do
    [[ -z "$v_a" || "$v_a" -gt "$v_b" ]] && echo 1 && return
    [[ -z "$v_b" || "$v_b" -gt "$v_a" ]] && echo -1 && return

    v_a=("${v_a[@]:1}")
    v_b=("${v_b[@]:1}")
  done

  echo 0
}

Hãy bình luận và đề xuất cải tiến.


1

Bạn có thể sử dụng phiên bản CLI để kiểm tra các ràng buộc của phiên bản

$ version ">=1.0, <2.0" "1.7"
$ go version | version ">=1.9"

Ví dụ về kịch bản Bash:

#!/bin/bash

if `version -b ">=9.0.0" "$(gcc --version)"`; then
  echo "gcc version satisfies constraints >=9.0.0"
else
  echo "gcc version doesn't satisfies constraints >=9.0.0"
fi

0

Tôi đã đi qua và giải quyết vấn đề này, để thêm một câu trả lời (và ngắn hơn và đơn giản hơn) ...

Lưu ý đầu tiên, so sánh shell mở rộng đã thất bại vì bạn có thể đã biết ...

    if [[ 1.2.0 < 1.12.12 ]]; then echo true; else echo false; fi
    false

Sử dụng sort -t '.'- g (hoặc sort -V như được đề cập bởi kanaka) để đặt hàng các phiên bản và so sánh chuỗi bash đơn giản tôi đã tìm thấy một giải pháp. Tệp đầu vào chứa các phiên bản trong cột 3 và 4 mà tôi muốn so sánh. Điều này lặp lại thông qua danh sách xác định một trận đấu hoặc nếu cái này lớn hơn cái kia. Hy vọng điều này vẫn có thể giúp bất cứ ai muốn làm điều này bằng cách sử dụng bash đơn giản nhất có thể.

while read l
do
    #Field 3 contains version on left to compare (change -f3 to required column).
    kf=$(echo $l | cut -d ' ' -f3)
    #Field 4 contains version on right to compare (change -f4 to required column).
    mp=$(echo $l | cut -d ' ' -f4)

    echo 'kf = '$kf
    echo 'mp = '$mp

    #To compare versions m.m.m the two can be listed and sorted with a . separator and the greater version found.
    gv=$(echo -e $kf'\n'$mp | sort -t'.' -g | tail -n 1)

    if [ $kf = $mp ]; then 
        echo 'Match Found: '$l
    elif [ $kf = $gv ]; then
        echo 'Karaf feature file version is greater '$l
    elif [ $mp = $gv ]; then
        echo 'Maven pom file version is greater '$l
   else
       echo 'Comparison error '$l
   fi
done < features_and_pom_versions.tmp.txt

Cảm ơn blog của Barry về ý tưởng sắp xếp ... ref: http://bkhome.org/blog/?viewDetailed=02199


0
### the answer is does we second argument is higher
function _ver_higher {
        ver=`echo -ne "$1\n$2" |sort -Vr |head -n1`
        if [ "$2" == "$1" ]; then
                return 1
        elif [ "$2" == "$ver" ]; then
                return 0
        else
                return 1
        fi
}

if _ver_higher $1 $2; then
        echo higher
else
        echo same or less
fi

Nó khá đơn giản và nhỏ.


Điều này sẽ phá vỡ khi có dấu gạch chéo ngược trong các phiên bản, thay thế tốt hơn echo -ne "$1\n$2"bằng printf '%s\n ' "$1" "$2". Ngoài ra, tốt hơn là sử dụng $()thay vì phân tích ngược.
phk

0

Nhờ giải pháp của Dennis, chúng tôi có thể mở rộng nó để cho phép các toán tử so sánh '>', '<', '=', '==', '<=' và '> ='.

# compver ver1 '=|==|>|<|>=|<=' ver2
compver() { 
    local op
    vercomp $1 $3
    case $? in
        0) op='=';;
        1) op='>';;
        2) op='<';;
    esac
    [[ $2 == *$op* ]] && return 0 || return 1
}

Sau đó chúng ta có thể sử dụng các toán tử so sánh trong các biểu thức như:

compver 1.7 '<=' 1.8
compver 1.7 '==' 1.7
compver 1.7 '=' 1.7

và chỉ kiểm tra đúng / sai của kết quả, như:

if compver $ver1 '>' $ver2; then
    echo "Newer"
fi

0

Đây là một phiên bản bash thuần túy khác, nhỏ hơn câu trả lời được chấp nhận. Nó chỉ kiểm tra xem một phiên bản nhỏ hơn hoặc bằng "phiên bản tối thiểu" hay không và nó sẽ kiểm tra các chuỗi chữ số theo từ vựng, thường cho kết quả sai ("ảnh chụp nhanh" không muộn hơn "phát hành", để đưa ra một ví dụ phổ biến) . Nó sẽ hoạt động tốt cho chính / phụ.

is_number() {
    case "$BASH_VERSION" in
        3.1.*)
            PATTERN='\^\[0-9\]+\$'
            ;;
        *)
            PATTERN='^[0-9]+$'
            ;;
    esac

    [[ "$1" =~ $PATTERN ]]
}

min_version() {
    if [[ $# != 2 ]]
    then
        echo "Usage: min_version current minimum"
        return
    fi

    A="${1%%.*}"
    B="${2%%.*}"

    if [[ "$A" != "$1" && "$B" != "$2" && "$A" == "$B" ]]
    then
        min_version "${1#*.}" "${2#*.}"
    else
        if is_number "$A" && is_number "$B"
        then
            [[ "$A" -ge "$B" ]]
        else
            [[ ! "$A" < "$B" ]]
        fi
    fi
}

0

Một cách tiếp cận khác (phiên bản sửa đổi của @joynes) so sánh các phiên bản chấm như được hỏi trong câu hỏi
(ví dụ: "1.2", "2.3.4", "1.0", "1.10.1", v.v.).
Số lượng vị trí tối đa phải được biết trước. Cách tiếp cận mong đợi tối đa 3 vị trí phiên bản.

expr $(printf "$1\n$2" | sort -t '.' -k 1,1 -k 2,2 -k 3,3 -g | sed -n 2p) != $2

sử dụng ví dụ:

expr $(printf "1.10.1\n1.7" | sort -t '.' -k 1,1 -k 2,2 -k 3,3 -g | sed -n 2p) != "1.7"

trả về: 1 kể từ 1.10.1 lớn hơn 1.7

expr $(printf "1.10.1\n1.11" | sort -t '.' -k 1,1 -k 2,2 -k 3,3 -g | sed -n 2p) != "1.11"

trả về: 0 vì 1.10.1 thấp hơn 1.11


0

Đây là một giải pháp Bash thuần túy hỗ trợ sửa đổi (ví dụ: '1.0-r1'), dựa trên câu trả lời được đăng bởi Dennis Williamson . Nó có thể dễ dàng được sửa đổi để hỗ trợ các công cụ như '-RC1' hoặc trích xuất phiên bản từ một chuỗi phức tạp hơn bằng cách thay đổi biểu thức thông thường.

Để biết chi tiết về việc triển khai, vui lòng tham khảo các nhận xét trong mã và / hoặc kích hoạt mã gỡ lỗi được bao gồm:

#!/bin/bash

# Compare two version strings [$1: version string 1 (v1), $2: version string 2 (v2)]
# Return values:
#   0: v1 == v2
#   1: v1 > v2
#   2: v1 < v2
# Based on: https://stackoverflow.com/a/4025065 by Dennis Williamson
function compare_versions() {

    # Trivial v1 == v2 test based on string comparison
    [[ "$1" == "$2" ]] && return 0

    # Local variables
    local regex="^(.*)-r([0-9]*)$" va1=() vr1=0 va2=() vr2=0 len i IFS="."

    # Split version strings into arrays, extract trailing revisions
    if [[ "$1" =~ ${regex} ]]; then
        va1=(${BASH_REMATCH[1]})
        [[ -n "${BASH_REMATCH[2]}" ]] && vr1=${BASH_REMATCH[2]}
    else
        va1=($1)
    fi
    if [[ "$2" =~ ${regex} ]]; then
        va2=(${BASH_REMATCH[1]})
        [[ -n "${BASH_REMATCH[2]}" ]] && vr2=${BASH_REMATCH[2]}
    else
        va2=($2)
    fi

    # Bring va1 and va2 to same length by filling empty fields with zeros
    (( ${#va1[@]} > ${#va2[@]} )) && len=${#va1[@]} || len=${#va2[@]}
    for ((i=0; i < len; ++i)); do
        [[ -z "${va1[i]}" ]] && va1[i]="0"
        [[ -z "${va2[i]}" ]] && va2[i]="0"
    done

    # Append revisions, increment length
    va1+=($vr1)
    va2+=($vr2)
    len=$((len+1))

    # *** DEBUG ***
    #echo "TEST: '${va1[@]} (?) ${va2[@]}'"

    # Compare version elements, check if v1 > v2 or v1 < v2
    for ((i=0; i < len; ++i)); do
        if (( 10#${va1[i]} > 10#${va2[i]} )); then
            return 1
        elif (( 10#${va1[i]} < 10#${va2[i]} )); then
            return 2
        fi
    done

    # All elements are equal, thus v1 == v2
    return 0
}

# Test compare_versions [$1: version string 1, $2: version string 2, $3: expected result]
function test_compare_versions() {
    local op
    compare_versions "$1" "$2"
    case $? in
        0) op="==" ;;
        1) op=">" ;;
        2) op="<" ;;
    esac
    if [[ "$op" == "$3" ]]; then
        echo -e "\e[1;32mPASS: '$1 $op $2'\e[0m"
    else
        echo -e "\e[1;31mFAIL: '$1 $3 $2' (result: '$1 $op $2')\e[0m"
    fi
}

echo -e "\nThe following tests should pass:"
while read -r test; do
    test_compare_versions $test
done << EOF
1            1            ==
2.1          2.2          <
3.0.4.10     3.0.4.2      >
4.08         4.08.01      <
3.2.1.9.8144 3.2          >
3.2          3.2.1.9.8144 <
1.2          2.1          <
2.1          1.2          >
5.6.7        5.6.7        ==
1.01.1       1.1.1        ==
1.1.1        1.01.1       ==
1            1.0          ==
1.0          1            ==
1.0.2.0      1.0.2        ==
1..0         1.0          ==
1.0          1..0         ==
1.0-r1       1.0-r3       <
1.0-r9       2.0          <
3.0-r15      3.0-r9       >
...-r1       ...-r2       <
2.0-r1       1.9.8.21-r2  >
1.0          3.8.9.32-r   <
-r           -r3          <
-r3          -r           >
-r3          -r3          ==
-r           -r           ==
0.0-r2       0.0.0.0-r2   ==
1.0.0.0-r2   1.0-r2       ==
0.0.0.1-r7   -r9          >
0.0-r0       0            ==
1.002.0-r6   1.2.0-r7     <
001.001-r2   1.1-r2       ==
5.6.1-r0     5.6.1        ==
EOF

echo -e "\nThe following tests should fail:"
while read -r test; do
    test_compare_versions $test
done << EOF
1            1            >
3.0.5-r5     3..5-r5      >
4.9.21-r3    4.8.22-r9    <
1.0-r        1.0-r1       ==
-r           1.0-r        >
-r1          0.0-r1       <
-r2          0-r2         <
EOF

echo -e "\nThe following line should be empty (local variables test):"
echo "$op $regex $va1 $vr1 $va2 $vr2 $len $i $IFS"

0

Wow ... đây là danh sách của một câu hỏi cũ, nhưng tôi nghĩ đây là một câu trả lời khá thanh lịch. Đầu tiên chuyển đổi từng phiên bản được phân tách bằng dấu chấm thành mảng riêng, sử dụng mở rộng tham số shell (Xem Mở rộng tham số Shell ).

v1="05.2.3"     # some evil examples that work here
v2="7.001.0.0"

declare -a v1_array=(${v1//./ })
declare -a v2_array=(${v2//./ })

Bây giờ hai mảng có số phiên bản là một chuỗi số theo thứ tự ưu tiên. Rất nhiều giải pháp trên đưa bạn từ đó, nhưng tất cả đều xuất phát từ quan sát rằng chuỗi phiên bản chỉ là một số nguyên với một cơ sở tùy ý. Chúng ta có thể kiểm tra việc tìm chữ số không đều đầu tiên (như strcmp làm cho các ký tự trong chuỗi).

compare_version() {
  declare -a v1_array=(${1//./ })
  declare -a v2_array=(${2//./ })

  while [[ -nz $v1_array ]] || [[ -nz $v2_array ]]; do
    let v1_val=${v1_array:-0}  # this will remove any leading zeros
    let v2_val=${v2_array:-0}
    let result=$((v1_val-v2_val))

    if (( result != 0 )); then
      echo $result
      return
    fi

    v1_array=("${v1_array[@]:1}") # trim off the first "digit". it doesn't help
    v2_array=("${v2_array[@]:1}")
  done

  # if we get here, both the arrays are empty and neither has been numerically
  # different, which is equivalent to the two versions being equal

  echo 0
  return
}

Điều này lặp lại một số âm nếu phiên bản đầu tiên nhỏ hơn số thứ hai, số 0 nếu chúng bằng nhau và số dương nếu phiên bản đầu tiên lớn hơn. Một số đầu ra:

$ compare_version 1 1.2
-2
$ compare_version "05.1.3" "5.001.03.0.0.0.1"
-1
$ compare_version "05.1.3" "5.001.03.0.0.0"
0
$ compare_version "05.1.3" "5.001.03.0"
0
$ compare_version "05.1.3" "5.001.30.0"
-27
$ compare_version "05.2.3" "7.001.0.0"
-2
$ compare_version "05.1.3" "5.001.30.0"
-27
$ compare_version "7.001.0.0" "05.1.3"
2

Các trường hợp thoái hóa như, ".2" hoặc "3.0." không hoạt động (kết quả không xác định) và nếu các ký tự không phải là số xuất hiện bên cạnh '.' nó có thể thất bại (chưa được thử nghiệm) nhưng chắc chắn sẽ không được xác định. Vì vậy, điều này nên được kết hợp với chức năng khử trùng hoặc kiểm tra thích hợp cho định dạng hợp lệ. Ngoài ra, tôi chắc chắn với một số điều chỉnh, điều này có thể được thực hiện mạnh mẽ hơn mà không cần thêm quá nhiều hành lý.


0
function version_compare () {
  function sub_ver () {
    local len=${#1}
    temp=${1%%"."*} && indexOf=`echo ${1%%"."*} | echo ${#temp}`
    echo -e "${1:0:indexOf}"
  }
  function cut_dot () {
    local offset=${#1}
    local length=${#2}
    echo -e "${2:((++offset)):length}"
  }
  if [ -z "$1" ] || [ -z "$2" ]; then
    echo "=" && exit 0
  fi
  local v1=`echo -e "${1}" | tr -d '[[:space:]]'`
  local v2=`echo -e "${2}" | tr -d '[[:space:]]'`
  local v1_sub=`sub_ver $v1`
  local v2_sub=`sub_ver $v2`
  if (( v1_sub > v2_sub )); then
    echo ">"
  elif (( v1_sub < v2_sub )); then
    echo "<"
  else
    version_compare `cut_dot $v1_sub $v1` `cut_dot $v2_sub $v2`
  fi
}

### Usage:

version_compare "1.2.3" "1.2.4"
# Output: <

Tín dụng vào @Shellman

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.