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

bash - print regex captured groups

我有一个file.xml这么沉着:

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

我需要提取以下信息:

我认为最简洁的方法是使用带有 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>.*~  ~p' file.xml
)

检查变量内容:

declare -p major minor suffix

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

几点:

  • 如果不在 grep
  • 中使用 -P (perl) 模式,则无法使用 \d
  • grep 命令不 return 捕获组

使用这个 Perl 单行代码:

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

示例:

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

输出:

1.0
13
-alpha

Perl 单行代码使用这些命令行标志:
-e : 告诉 Perl 查找内联代码,而不是在文件中。
-n :一次循环输入一行,默认分配给 $_
-l : 在执行内联代码之前去除输入行分隔符(默认情况下在 *NIX 上为 "\n"),并在打印时附加它。

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