如何从字符串中取出所有数字并将它们相加?

如何从字符串中取出所有数字并将它们相加?

我必须解析生成的 .xml 文件来总结在某些软件上运行 testSuite 的结果。在我的一行中,例如:

<Summary failed="10" notExecuted="0" timeout="0" pass="18065" />

这表示失败、未执行和通过的测试数量。我需要计算出测试套件中有多少个测试,因此在上面的情况下我需要添加 10+0+18065 = 18075。

我怎样才能在 Bash 中做到这一点?

答案1

您可以使用xmlstarlet为了正确的 xml 解析。

对于您的问题:

total=0; \
for i in failed notExecuted pass; do \
    sum=`xmlstarlet sel -t -v "//Summary/@$i" test.xml`; \
    total=$(($sum + $total)); \
done; \
echo "Total=$total"

test.xml包含 xml 数据的文件在哪里。

答案2

使用perl

perl -lne 'my @a=$_=~/(\d+)/g;$sum+=$_ for @a; print $sum' file

使用awk

tr ' ' '\n' < file | 
    awk '/[0-9]+/ {gsub(/[^0-9]/, "", $0); sum+=$0} END {print sum}'

例子

% perl -lne 'my @a=$_=~/(\d+)/g;$sum+=$_ for @a; print $sum' foo
18075

% tr ' ' '\n' < foo | 
    awk '/[0-9]+/ {gsub(/[^0-9]/, "", $0); sum+=$0} END {print sum}' 
18075

% cat foo
<Summary failed="10" notExecuted="0" timeout="0" pass="18065" />

答案3

只需丢弃所有非数字和非空格的字符:

echo '<Summary failed="10" notExecuted="0" timeout="0" pass="18065" />'|\
sed -e 's/[^0-9 ]//g'

给出

10 0 0 18065

可以使用 dc 来完成求和(根据请求过滤超时字段)

echo '<Summary failed="10" notExecuted="0" timeout="0" pass="18065" />'|\
sed -e 's/timeout="[0-9]*" //' \
    -e 's/[^0-9 ]//g' \
    -e 's/^ *//' \
    -e 's/ *$//' \
    -e 's/ /+/g' \
    -e 's/^/0 /' \
    -e 's/$/pq/'|dc

描述

作为 sed 脚本,它看起来像这样

s/timeout="[0-9]*" //    #remove the timeout
s/[^0-9 ]//g             #drop anything but numbers and spaces
s/^ *//                  #drop spaces at the beginning of the line
s/ *$//                  #drop spaces at the end of the line
s/ /+/g                  #replace remaining spaces with +
s/^/0 /                  #add a 0 to initialize the sum for dc
s/$/pq/                  #add print and quit command for dc

该脚本可以简单地与

INPUT|sed -f script.sed

。我留给您使用 sed 和 dc 来应用此脚本以进行多行输入。我写的只需要一行就可以了!

答案4

使用 XML 解析器,例如XML小星问题中给出的文件:

$ xml sel -t -m '//Summary' -v '@failed+@notExecuted+@timeout+@pass' -nl file.xml
18075

如果Summary找到的节点有多个位置,则每个节点都会输出一行。

在某些系统上,XMLStarlet 安装为xmlstarlet而不是安装为xml.

相关内容