从字符串中提取版本号

13

我有一个包含组件和版本号的字符串:

data-c(kuh-small1);divider-bin-1.4.4;divider-conf-1.3.3-w(1,16);storage-bin-1.5.4;storage-conf-1.5.0-w(1);worker-bin-4.5.1;worker-conf-4.4.1-c(kuh)-win2

对于一个 shell 脚本,我需要提取 divider 二进制文件的版本号。因此,我需要得到:

1.4.4

如何才能很好地做到这一点?使用 sed?


1
@fedorqui 你说得对!我想我想指出的是 https://dev59.com/V1nUa4cB1Zd3GeqPXiBN 我删除了我的第一个评论,并用另一个评论替换了它。 - oHo
还可以参考一个关于 sed类似答案,但也有一些基于命令 cutperlawk 的答案。 - oHo
5个回答

20

参照Kent的回答,可以这样操作:

grep -Po '(?<=divider-bin-)\d.\d.\d'

甚至更好:

grep -Po '(?<=divider-bin-)[^;]+'

它从divider-bin-开始grep,直到找到;字符。这样任何NNN.NNN. ... . NNN格式都可以使用(无论有多少个NN块)。

测试:

$ echo "data-c(kuh-small1);divider-bin-1.4.4;divider-conf-1.3.3-w(1,16);storage-bin-1.5.4;storage-conf-1.5.0-w(1);worker-bin-4.5.1;worker-conf-4.4.1-c(kuh)-win2" | grep -Po '(?<=divider-bin-)[^;]+'
1.4.4
$ echo "data-c(kuh-small1);divider-bin-1.4;divider-conf-1.3.3-w(1,16);storage-bin-1.5.4;storage-conf-1.5.0-w(1);worker-bin-4.5.1;worker-conf-4.4.1-c(kuh)-win2" | grep -Po '(?<=divider-bin-)[^;]+'
1.4

如何使用grep命令查找第二个;字符? - Koustuv Sinha
我有一个类似的需求,我把停止字符设为\s来获取版本号(例如3.2.1),现在我只想获取到3.2。使用.作为停止字符我只能获取到3。 - Koustuv Sinha
@KoustuvSinha 应该使用 grep -Po '(?<=divider-bin-)\d.\d' 命令。否则,请提供更多细节并提出新问题。 - fedorqui
它不起作用。它会显示:无效选项--P - MA1
@fedorqui 我正在使用(BSD grep,GNU 兼容)。有没有其他方法可以在不安装额外工具的情况下完成这个任务? - MA1
显示剩余4条评论

7

这个通用答案适用于所有情况

我使用以下三个 命令中的一个,具体取决于预期的输入字符串:

  1. The input string always contain one single version

     perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' 
    
  2. To extract several versions (several lines)

     perl -pe 'if(($_)=/([0-9]+([.][0-9]+)+)/){$_.="\n"}'
    
  3. To extract one single version (the first one) in all cases

     perl -pe 'if(($v)=/([0-9]+([.][0-9]+)+)/){print"$v\n";exit}$_=""'
    

  1. 最简单的

第一条命令行不包含最后的换行符:
> gcc --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
5.3.1

> bash --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
4.2.46

> perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' <<< 'A2 33. Z-0.1.2.3.4..5'
0.1.2.3.4

> uname -a | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
3.10.0

> lsb_release | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
4.1

将版本存储在shell变量中:

> v=$( gcc --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' )
> echo "GCC version is '$v'"
GCC version is '5.3.1'

但对于多版本号无法成功:

> gwenview --version
Qt: 4.8.5
KDE Development Platform: 4.14.8
Gwenview: 4.10.4

> gwenview --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
4.8.54.14.84.10.4
  1. 每行提取一个版本

> gwenview --version | perl -pe 'if(($_)=/([0-9]+([.][0-9]+)+)/){$_.="\n"}' 
4.8.4
4.14.8
4.10.4

> mvn --version
Apache Maven 3.0.4
Maven home: /usr/share/maven
Java version: 1.7.0_25, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-7-openjdk-amd64/jre
Default locale: fr_FR, platform encoding: UTF-8
OS name: "linux", version: "3.11.0-13-generic", arch: "amd64", family: "unix"

> mvn --version | perl -pe 'if(($_)=/([0-9]+([.][0-9]+)+)/){$_.="\n"}'
3.0.4
1.7.0
3.11.0
  1. 仅提取第一个版本

> gwenview --version | perl -pe 'if(($v)=/([0-9]+([.][0-9]+)+)/){print"$v\n";exit}$_=""'
4.8.5

创建别名:
> alias extractor='perl -pe '\''if(($v)=/([0-9]+([.][0-9]+)+)/){print"$v\n";exit}$_=""'\'''

或者如果您使用最近的

> alias extractor=$'perl -pe \'if(($v)=/([0-9]+([.][0-9]+)+)/){print"$v\n";exit}$_=""\''

> v=$( mvn --version | extractor )
> echo "The maven version is '$v'"
The maven version is '3.0.4'

'client_release/7.18/7.18.0/'。 - user12859859

2

sed可以轻松处理这个问题...

string="ata-c(kuh-small1);divider-bin-1.4.4;divider-conf-1.3.3-w(1,16);storage-bin-1.5.4;storage-conf-1.5.0-w(1);worker-bin-4.5.1;worker-conf-4.4.1-c(kuh)-win2"

echo $string | sed "s/^.*divider-bin-\([0-9.]*\).*/\1/"
1.4.4

还有一些其他的事情可以做来加强它...比如当你到达";"时停止获取版本号。

sed "s/^.*divider-bin-\([^;]*\).*/\1/"

0
sed -n "s/.*;divider-bin-\([0-9][^;]*\);.*/\1/p"

infos在;divider-bin-和下一个;之间,并以数字开头。这是为了确保没有Other-divider-bin-divider-bin-and-hex-会干扰您的请求。如果找不到,则返回空字符串。

为了详尽无遗(假设版本号只包含数字和点号)

sed -n "s/.*;divider-bin-\([0-9.]\{1,\}\)\([^0-9.;][^;]*\)*;.*/\1/p"

0

你也可以使用 Perl:

perl -wne '/divider-bin-(.+?);/ and print "$1\n"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接