从文件

时间:2017-11-19 00:37:51

标签: bash shell unix aix

我有一个包含多个属性的大单行(只有一行)的文件。文件类似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脚本/命令帮助我吗?

4 个答案:

答案 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"