簡體   English   中英

在bash上排序版本字符串

[英]Sort version strings on bash

STRINGS.txt的示例內容:

    3.0.3
    3.0.11.2
    3.0.11.1
    3.0.11
    3.0.16
    3.0.15.1
    3.0.15
    3.0.14
    3.0.10.3
    3.0.10.2
    3.0.10.1
    3.0.13.1
    3.0.10
    3.0.13
    3.0.9
    3.0.12
    3.0.8
    3.0.7.2
    3.0.7.1
    3.0.7
    3.0.9.2
    3.0.9.1
    3.0.2
    3.0.8.1
    3.0.6.1
    3.0.6
    3.0.5
    3.0.1
    3.0.0

是否可以僅使用bash對所有這些版本字符串進行排序,最新版本是否在頂部?

這是可能的,但卻是一項愚蠢的工作。 如果你有GNU排序:

sort -V -r <STRINGS.txt

......將完全按照你的要求行事。


現在,如果你真的沒有外部工具的意思,那么你就陷入了一些麻煩。 Freenode的#bash IRC頻道上的BlastHardcheese已經在本機bash中編寫了以下quicksort算法,我為了便於閱讀而修改了該算法,將compare函數分解為可重放,並使用Bash 4.3 namevars來處理可配置變量name(當然,后一個更改意味着需要一個非常新版本的bash):

# this needs to be replaced for this particular case
compare(){
  (( $1 >= $2 ))
}

swap(){
  declare -n a=$1
  local t
  t=${a[$2]}
  a[$2]=${a[$3]}
  a[$3]=$t
}

partition(){
  declare -n a=$1
  local c p x
  p=${a[$4]}
  c=$2
  swap "$1" "$3" "$4"
  for((x=$2;x<$3;x++)); do
    if ! compare "${a[x]}" "$p"; then
      swap "$1" "$x" "$c"
      ((c++))
    fi
  done
  swap "$1" "$2" "$c"
  n=$c
}

quicksort(){
  declare -n a=$1
  (( "$2" >= "$3" )) && return
  local i n
  i=$((($2+$3)/2))
  partition "$1" "$2" "$3" "$i"
  quicksort "$1" "$2" "$((n-1))"
  quicksort "$1" "$((n+1))" "$3"
}

...實現自己的比較功能,然后可以采用。

僅處理您在此處顯示的案例:

# we want to return 0 if the first version is equal or later than the second
version_compare(){
  local -a first second

  # Let's start with trivial cases:
  if [[ $1 = "$2" ]] || [[ $1 = "$2".* ]]; then : "$1 >= $2"; return 0; fi

  IFS=. read -r -a first <<<"$1"
  IFS=. read -r -a second <<<"$2"

  local k
  for k in "${!first[@]}"; do
    local a=${first[$k]} b=${second[$k]}
    : "Evaluating field $k ($a vs $b)"
    if [[ ! $b ]]; then
      # ie. first=1.1.1, second=1.1; though this should have been handled above
      : "$1 >= $2"; return 0;
    fi
    if (( $b > $a )); then
      : "$1 < $2"; return 1;
    fi
  done

  : "$1 >= $2"; return 0;
}
compare() {
  version_compare "$2" "$1" # reverse sort order
}

要執行文件IO,假設bash 4:

readarray -t versions <STRINGS.txt
quicksort versions 0 "$(( ${#versions[@]} - 1 ))"
printf '%s\n' "${versions[@]}"

我知道你不需要Python解決方案,但對於那些缺乏GNU sort (比如OS X)來說,確實是一種簡單的方法。

鑒於:

$ echo "$a"
3.0.3
3.0.11.2
3.0.11.1
3.0.11
3.0.16
3.0.15.1
3.0.15
3.0.14
3.0.10.3
3.0.10.2
3.0.10.1
3.0.13.1
3.0.10
3.0.13
3.0.9
3.0.12
3.0.8
3.0.7.2
3.0.7.1
3.0.7
3.0.9.2
3.0.9.1
3.0.2
3.0.8.1
3.0.6.1
3.0.6
3.0.5
3.0.1
3.0.0

Python 1班輪:

$ echo "$a" | python -c '
import sys, re; print "".join(sorted(sys.stdin.readlines(), key=lambda s: map(int, re.findall("\\d+", s)), reverse=True))'
3.0.16
3.0.15.1
3.0.15
3.0.14
3.0.13.1
3.0.13
3.0.12
3.0.11.2
3.0.11.1
3.0.11
3.0.10.3
3.0.10.2
3.0.10.1
3.0.10
3.0.9.2
3.0.9.1
3.0.9
3.0.8.1
3.0.8
3.0.7.2
3.0.7.1
3.0.7
3.0.6.1
3.0.6
3.0.5
3.0.3
3.0.2
3.0.1
3.0.0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM