我试图确定给定节点上哪个版本的 DB2 是最新的。我们将 DB2 软件安装在 /opt/IBM/db2 目录中。如果我列出我得到的目录
V10.5
V9.1
V9.5
V9.5fp10
V9.7
V9.7fp3
V9.7fp6
V9.7fp7
显然 10.5 是当前最新版本,但第一个条目并不总是最新的(即:当我们安装 V11.0 时)。有没有一种相对简单的方法来确定最新的(在 ksh93 中)?我可以将每个条目解析为主要/次要/修复包,但这似乎是劳动密集型的。
答案1
如果你有 GNU 工具,你可以使用ls -v
或者,使用 perl:
printf "%s\n" * | perl -e '
@sorted = map {$_->[1]}
sort {$a->[0] <=> $b->[0] or $a->[1] cmp $b->[1]}
map {/(\d+\.\d*)/ and [$1, $_]}
<>;
print $sorted[-1];
'
答案2
没有 GNU 工具,只有劳动密集型的 shell 脚本:
recentdb2 () (
cd /opt/IBM/db2 || return 1
highest=
himajor=
himinor=
hifp=
for dir in V*.*
do
[ ! -d "$dir" ] && continue
nov="${dir#V*}"
major="${nov%%.*}"
notmajor="${nov##*.}"
minor="${notmajor%%fp*}"
if [ "$minor" = "$notmajor" ]
then
# no FP
fp=0
else
fp="${notmajor##*fp}"
fi
# if highest major isn't set, set it and continue
# else compare major; if higher, set it and continue
# else compare minor; if higher, set it and continue
# else compare fp; if higher, set it
if [ "${himajor:-notset}" = "notset" ]
then
highest="$dir"
himajor="$major"
himinor="$minor"
hifp="$fp"
continue
fi
if [ "$major" -gt "$himajor" ]
then
highest="$dir"
himajor="$major"
himinor="$minor"
hifp="$fp"
continue
elif [ "$major" -eq "$himajor" ] && [ "$minor" -gt "$himinor" ]
then
highest="$dir"
himajor="$major"
himinor="$minor"
hifp="$fp"
continue
elif [ "$major" -eq "$himajor" ] && [ "$minor" -eq "$himinor" ] && [ "$fp" -gt "$hifp" ]
then
highest="$dir"
himajor="$major"
himinor="$minor"
hifp="$fp"
fi
# else, the current value is less than the highest value, drop it and continue on
done
printf "%s" "$highest"
)
这定义了一个函数,它将(尝试)从 /opt/IBM/db2 返回最高级别的 DB2 目录。
该函数全部在子 shell 中运行,因此:
- 它创建的变量在完成时消失,并且
- 也
cd
与子 shell 隔离
然后,该函数循环访问 /opt/IBM/db2 目录中与 glob 模式匹配的条目V*.*
—— 如果您有诸如V11
不带任何点的版本,请调整此项。第一个测试是确保我们不会被流浪者愚弄文件匹配这个模式。
劳动开始:我们剥去前导V
(“无 V”),然后计算:
- 主数字是第一个句点之前的所有内容
- “非主要数字”是第一个周期之后的所有内容
- 次要编号是从“非主要编号”到任何一个的部分
fp
- 如果名称中有一个
fp
(从完整的“非主要数字”字符串到次要数字没有变化),则将 fp 设置为该名称,否则将其设置为零
正如评论所说,我们测试并适当设置“高”变量。我们遇到的第一个目录将进入第一个条件——默认情况下它是最高级别。
然后将后续目录条目与当前最高的主要版本、次要版本和 fp 版本进行比较。
循环完成后,该函数将打印出最新的目录名称。
通过创建脚本或在代码中获取来使用该函数,然后调用该函数:
h=$(recentdb2)
答案3
和zsh
:
list=(/opt/IBM/db2/V*(Nn:t))
其中n
glob 限定符启用数字排序完全符合您的要求,这里从最旧的 ( $list[1]
) 到最新的 ( $list[-1]
) 排序。
与ksh93
,如果它是用ls
内置的构建的ast-open
,您可以使用它版本种类:
(cd /opt/IBM/db2 && command /opt/ast/bin/ls -d -y version V*)
command /opt/ast/bin/ls
调用该/opt/ast/bin/ls
命令或相应的内置等效命令(如果存在),无论/opt/ast/bin/ls
文件系统上是否存在。
您还可以这样做:
PATH=/opt/ast/bin:$PATH
ls -d -y version V*
为了使该ls
内置函数优先于系统中的/bin
或/usr/bin
。
否则,你可以这样做:
tmp=(/opt/IBM/db2/~(N)V*) # ~(N) equivalent of zsh's N
tmp=("${tmp[@]##*/}") # equivalent of :t
typeset -A map
# build an associative array where the key is the element with
# all the numbers in them 0-padded to 20 digits. Append a counter
# to make sure all keys are unique.
typeset -Z 20 n=0
for i in "${tmp[@]}"; do
k=${i//+([0-9])/00000000000000000000\1}
k=${k//+(0){20}([0-9])/\2}
map[$k-$n]=$i
((n++))
done
# sort the keys of the associative array into $@:
set -s -- "${!map[@]}"
# fill $list with the values for those (now sorted) keys.
typeset -a list
for i do
list+=("${map[$i]}")
done
printf -- '- %s\n' "${list[@]}"
((${#list[@]})) && printf 'Newest: %s\n' "${list[@]: -1}"
在你的样本上,这给出了:
- V9.1
- V9.5
- V9.5fp10
- V9.7
- V9.7fp3
- V9.7fp6
- V9.7fp7
- V10.5
Newest: V10.5