我想获取 glibc 的版本,并在 if 语句中使用它,说明 glibc 是否小于 2.15。
然而问题是,当使用 ldd --version 时,它会作为字符串输出。我需要将其转换为整数才能进行小于比较。
以前我是这样做的
if [ "$(ldd --version | sed -n '1 p' | tr -cd '[:digit:]' | tail -c 3)" -lt 215 ]; then
这并不是很好,因为我必须删除小数点并且无法给出真实的版本号比较。另一个问题是某些版本的 glibc 有多个小数点(参见此处https://en.wikipedia.org/wiki/GNU_C_Library#Version_history)这意味着我现有的比较会混乱。
因此,为此,我需要能够将 glibc 版本完整地转换为整数,并正确比较版本号,即使有多个小数点。
有任何想法吗?谢谢
答案1
ldd --version | sed 's/.* //;q' | awk -F. '{ if ($1 > 2 || ($1 == 2 && $2 >= 15)) { exit 0 } else {exit 1} }'
解释:
该sed
命令获取 的第一行输出ldd --version
,去掉最后一个空格之前的所有内容,然后退出(因此它只打印数字)。
设置为字段分隔符的-F
标志。awk
.
如果第一个数字(点之前)大于 2,或者如果第一个数字为 2 并且第二个数字至少为 15,则awk
退出状态将为“true”。否则就是假的。
您可以在脚本中使用它,bash
如下所示:
if ldd --version | sed 's/.* //;q' | awk -F. '{ if ($1 > 2 || ($1 == 2 && $2 >= 15)) { exit 0 } else {exit 1} }' ; then
echo "Version is 2.15 or later"
else
echo "Version is too old."
fi
答案2
sort
可以对版本号进行排序;利用这一点,你可以写这样的东西:
if [ $(printf '%s\n2.15\n' $(ldd --version | sed -n '1s/.* //p') | sort -V | head -n 1) != 2.15 ]; then
# ...
fi
printf '%s\n2.15\n' $(ldd --version | sed -n '1s/.* //p')
打印ldd
的版本号并2.15
在两个单独的行中sort -V
按升序对它们进行排序并head -n 1
打印第一行;外部命令替换被输出替换,并将输出与2.15
;如果输出不是2.15
,则if
执行主体。
我的机器上的示例输出ldd
2.21
:
% [ $(printf '%s\n2.15\n' $(ldd --version | sed -n '1s/.* //p') | sort -V | head -n 1) != 2.15 ] && printf 'Version %s is lower than 2.15\n' $(ldd --version | sed -n '1s/.* //p') || printf 'Version %s is equal or higher than 2.15\n' $(ldd --version | sed -n '1s/.* //p')
Version 2.21 is equal or higher than 2.15
一些硬编码值的示例输出,只是为了演示该方法处理版本排序的复杂性:
% glibc_version=2.15
% [ $(printf '%s\n2.15\n' $glibc_version | sort -V | head -n 1) != 2.15 ] && printf 'Version %s is lower than 2.15\n' $glibc_version || printf 'Version %s is equal or higher than 2.15\n' $glibc_version
Version 2.15 is equal or higher than 2.15
% glibc_version=2.16
% [ $(printf '%s\n2.15\n' $glibc_version | sort -V | head -n 1) != 2.15 ] && printf 'Version %s is lower than 2.15\n' $glibc_version || printf 'Version %s is equal or higher than 2.15\n' $glibc_version
Version 2.16 is equal or higher than 2.15
% glibc_version=2.15.1
[ $(printf '%s\n2.15\n' $glibc_version | sort -V | head -n 1) != 2.15 ] && printf 'Version %s is lower than 2.15\n' $glibc_version || printf 'Version %s is equal or higher than 2.15\n' $glibc_version
Version 2.15.1 is equal or higher than 2.15
% glibc_version=2.14
% [ $(printf '%s\n2.15\n' $glibc_version | sort -V | head -n 1) != 2.15 ] && printf 'Version %s is lower than 2.15\n' $glibc_version || printf 'Version %s is equal or higher than 2.15\n' $glibc_version
Version 2.14 is lower than 2.15
答案3
不要将版本字符串转换为整数。比较字符串。
这对于您的用例来说有点过分了,但这里有一个比较典型版本字符串的 shell 函数。它遵循的一个子集Debian版本比较规则:
- 版本是逐块比较的。每个块由最大字符序列组成,该字符序列要么完全由数字组成,要么不包含数字。
- 非数字序列按字典顺序进行比较。
- 数字序列根据十进制值进行比较。特别是,前导零是无关紧要的。
请注意,最后一点:1.01
被视为等于1.1
。这是要支付1.1
并被1.9
认为低于的价格1.10
。
此代码需要 dash、bash、ksh 或 zsh。要将其与其他 shell(例如 BusyBox sh)一起使用,请将对by 的调用替换为。[ "STRING1" \> "STRING2" ]
expr "aSTRING1" \> "aSTRING2"
version_ge () (
version1="$1" version2="$2"
while true; do
prefix1="${version1%%[0-9]*}" prefix2="${version2%%[0-9]*}"
if [ "$prefix1" \> "$prefix2" ]; then return 0; fi
if [ "$prefix2" \> "$prefix1" ]; then return 1; fi
version1="${version1#"$prefix1"}" version2="${version2#"$prefix2"}"
prefix1="${version1%%[!0-9]*}" prefix2="${version2%%[!0-9]*}"
version1="${version1#"$prefix1"}" version2="${version2#"$prefix2"}"
case "$prefix2" in
0*[!0]*) prefix2="${prefix2##"${prefix2%%[!0]*}"}";;
*[!0]*) :;;
*) return 0;;
esac
case "$prefix1" in
0*[!0]*) prefix1="${prefix1##"${prefix1%%[!0]*}"}";;
*[!0]*) :;;
*) return 1;;
esac
if [ "${#prefix1}" -gt "${#prefix2}" ]; then return 0; fi
if [ "${#prefix1}" -lt "${#prefix2}" ]; then return 1; fi
if [ "$prefix1" \> "$prefix2" ]; then return 0; fi
if [ "$prefix2" \> "$prefix1" ]; then return 1; fi
done
)