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使其能够与可配置变量名一起使用(当然,后面的更改意味着需要一个非常新的bash版本):
compare
# 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 }
假设bash 4,执行文件IO:
readarray -t versions <STRINGS.txt quicksort versions 0 "$(( ${#versions[@]} - 1 ))" printf '%s\n' "${versions[@]}"