问题描述
...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