3

我需要做的就是从以下文件中提取版本信息:

 my_archive_1.1.1.201_x86_64.tgz

我正在尝试提取版本号1.1.1和版本号201。通常我将 python 用于这些目的,但有人要求我不要这样做。我如何只使用 bash 来做到这一点?文件名将始终采用以下形式

([A-Za-z_]+)_([0-9]+\.[0-9]+\.[0-9]+)\.([0-9]+)_x86_64\.tgz

这些组在括号中。如果你从 1 开始数,我需要第二组和第三组。

4

3 回答 3

6

使用纯 BASH:

s='my_archive_1.1.1.201_x86_64.tgz'
[[ $s =~ ^[^_]+_[^_]+_(([^.]+\.){2}[^.]+)\.([^_]+) ]] && \
        echo "${BASH_REMATCH[1]}, ${BASH_REMATCH[3]}"

输出:

1.1.1, 201

使用您自己的正则表达式:

[[ $s =~ ([A-Za-z_]+)_([0-9]+\.[0-9]+\.[0-9]+).([0-9]+)_x86_64\.tgz ]] && \
        echo "${BASH_REMATCH[2]}, ${BASH_REMATCH[3]}"
于 2013-08-12T07:12:49.467 回答
2

您可以使用简单的字符串替换来提取子字符串。你真的不需要正则表达式。作为奖励,这可以移植到其他 POSIX shell。这是否更简单是一个品味问题,也取决于问题。

s='my_archive_1.1.1.201_x86_64.tgz'
# ${s%%_[0-9]*} is 'my-archive'
s=${s#${s%%_[0-9]*}_}
# s='1.1.1.201_x86_64.tgz'
s=${s%%_*}
# s='1.1.1.201'
release=${s##*.}
version=${s%."$release"}

您可能还想尝试set

s='my_archive_1.1.1.201_x86_64.tgz'
oldIFS=$IFS
IFS=_
set $s
# $1 = my, $2=archive, $3=1.1.1.201, $4=x86, $5=64.tgz
# Shift until $1 contains only numbers and periods
while $1; do
    case $1 in *[!.0-9]* ) shift ;; *) break ;; esac
done
IFS=.
set $1
version=$1.$2.$3
release=$4
IFS=$oldIFS
于 2013-08-12T07:52:59.380 回答
1

不使用正则表达式的另一种选择:

split=`echo "my_archive_1.1.1.201_x86_64.tgz" | cut -d'_' -f3`
versionnumber=`echo $split | cut -d'.' -f1,2,3`
releasenumber=`echo $split | cut -d'.' -f4`
echo "$versionnumber $releasenumber"
于 2013-08-12T19:19:22.900 回答