我有一个包含多个属性的大单行(只有一行)的文件。文件类似XML,但不是有效的XML,因此不确定是否可以使用XML实用程序。该行如下所示:
<a="1" b="2" time="10" c="3" time="1" time="3" d="1" e="1" f="1" time="10" .... />
我想提取所有的时间值并总结一下。 time
可以是该行中的任何位置。 GNU grep不可用,因此无法使用grep -oP
有人可以用bash脚本/命令帮助我吗?
答案 0 :(得分:1)
你不需要GNU grep&#39; -P
:
grep -o 'time="[^"]*"' infile | cut -d '"' -f2 | paste -s -d+ | bc
这会提取所有time="dd"
字符串:
time="10"
time="1"
time="3"
time="10"
以cut
作为分隔符的 "
然后提取第二个字段,即数字:
10
1
3
10
paste -s -d+
将所有内容放回一行,使用+
作为分隔符:
10+1+3+10
和bc
计算结果:
21
如果你的grep甚至没有-o
选项,我刚才意识到它既不是POSIX也不是AIX grep,你可以做类似的事情
tr ' ' '\n' < infile | grep 'time=' | cut -d '"' -f2 | paste -s -d+ | bc
首先在单独的行上获取每个键/值对。这适用于任何具有这些实用程序的POSIX一致版本的系统。
答案 1 :(得分:0)
你可以使用Perl来提取time="..."
中的数字并总结它们:
perl -pne 'use List::Util qw(reduce); $_ = reduce { $a + $b } /time="(\d+)"/g' < file
技巧是Perl中的/.../
运算符返回捕获组中的值列表。
在此示例中,time="..."
。
List::Util::reduce
是计算他们的总和。
-ne
是将stdin
的内容读入$_
变量,
并且-p
将自动打印$_
变量的值(我们用值的总和替换)。
答案 2 :(得分:0)
awk
怎么样?
awk 'BEGIN {RS=" "; FS="\""; sum=0} /time*/{sum+=$2} END {print sum}' data.xml
说明:
RS
代表记录分隔符,因此我们要求awk
一次处理一个 key = value 对。FS
代表字段分隔符,因此我们将记录拆分为"
,这样可以轻松提取数值。/time*/{sum+=$2}
将匹配以时间开头的所有记录,并将该值添加到我们的全局sum
。sum
累积的值。答案 3 :(得分:0)
有趣的总结。您也可以使用grep -ow
和bash单独执行此操作。注意:要使其符合POSIX shell,您需要将grep
表达式的输出传递给read
,而不是使用进程替换。 (并使用sum="${sum}+$n"
代替+=
变体)您可以执行以下操作:
$ c=0; sum=; \
while read -r n; do \
((c > 0)) && sum+="+$n" || sum="$n"; ((c++)); \
done < <(grep -ow "[0-9]*" yourfile); \
echo $((sum)))
33
将其添加到混合物中。如果您了解所有答案,则可以使用更多工具添加到shell工具箱中。
输入文件
$ cat yourfile
a="1" b="2" time="10" c="3" time="1" time="3" d="1" e="1" f="1" time="10"