bash-打印正则表达式捕获的组

问题描述

我有一个 file.xml ,它的组成如下:

...some xml text here...
    <Version>1.0.13-alpha</Version>
...some xml text here...

我需要提取以下信息:

  • mayor_and_minor_release_number -> 1.0
  • 补丁号-> 13
  • 后缀-> -alpha

我认为最干净的方法是使用 grep 命令的正则表达式:

<Version>(\d+\.\d+)\.(\d+)([\w-]+)?<\/Version>

我已经用regex101检查了此正则表达式的正确性,实际上它似乎可以正确捕获我要查找的3个字段。但是问题来了,因为我不知道如何打印这些字段。

cat file.xml | grep "<Version>(\d+\.\d+)\.(\d+)([\w-]+)?<\/Version>" -oP

此命令将打印整行,因此非常没用。

站点上的几篇文章都写过关于该主题文章,因此我也尝试使用 bash native 正则表达式支持效果不佳:

regex="<Version>(\d+\.\d+)\.(\d+)([\w-]+)?<\/Version>"
txt=$(cat file.xml)
[[ "$txt" =~ $regex ]]     --> it fails!
echo "${BASH_REMATCH[*]}"

很抱歉,但我不知道如何解决这个问题。所需的输出应为:

1.0
13
-alpha

解决方法

您可以将此read + sed解决方案与与您类似的正则表达式一起使用:

read -r major minor suffix < <(
sed -nE 's~.*<Version>([0-9]+\.[0-9]+)\.([0-9]+)(-[^<]*)</Version>.*~\1 \2 \3~p' file.xml
)

检查变量内容:

declare -p major minor suffix

declare -- major="1.0"
declare -- minor="13"
declare -- suffix="-alpha"

几点:

  • \d中不使用-P(perl)模式就不能使用grep
  • grep命令不返回捕获组
,

使用此Perl单线版:

echo '<Version>1.0.13-alpha</Version>' | perl -lne 'print for m{<Version>(\d+\.\d+)\.(\d+)([\w-]+)?<\/Version>};'

示例:

1.0
13
-alpha

输出:

-e

Perl单行代码使用以下命令行标志:
-n:告诉Perl在代码中而不是在文件中查找代码。
$_:一次遍历输入一行,默认情况下将其分配给-l
"\n":在直接执行代码之前,先剥离输入行分隔符(默认为* NIX上的{{{1}}),并在打印时附加它。

另请参见:
perldoc perlrun: how to execute the Perl interpreter: command line switches