如何为每个多行匹配grep和执行命令

时间:2017-12-04 16:15:17

标签: bash grep

是否可以通过一个命令处理多行grep输出?

我有类似

的东西
<fulldata>
<value>1</value>
<value>2</value>
</fulldata>
<fulldata>
<value>2</value>
<value>3</value>
</fulldata>

并希望得到资产,标准偏差并自行处理数据元素。

在这种情况下,我想执行

function printStatistics {
        mean1=$(awk -F ';' '{print $1}' $1 | awk '{sum += $1; square += $1^2} END {print sum / NR}')
        deviation1=$(awk -F ';' '{print $1}' $1 | awk '{sum += $1; square += $1^2} END {print sqrt(square / NR - (sum/NR)^2)}')
        size=$(cat $1 | wc -l)
        echo $mean1 $deviation1 $size
}

具有预期结果(对于样本数据),理想情况下由换行符分隔:

1,5 0,7 2
2,5 0,7 2

运行

cat add.xml | grep "<fulldata" -A 2001 | while read line ; do echo "Line: $line" ; done
How to grep and execute a command (for every match)中建议的那样,确实会为每一行产生一个条目;但我希望每个条目都有一个条目(以便稍后在其上执行awk个内容。)

这对grep是否可行,或者这是另一种语言更合适的用例?

3 个答案:

答案 0 :(得分:1)

使用grep解析html / xml是不好的做法,因为它不可靠。如果您使用的是Mac OS X,则可以使用名为xmllint的预安装cli工具来选择特定元素。在linux上,您可以使用标准包管理器来获取它。

还有xgrep,还有其他我不知道的事情。

答案 1 :(得分:1)

awk救援!

$ awk -v RS='\n?</?fulldata>\n' -F'\n' '
        !(NR%2){gsub("</?value>",""); 
                s=ss=0; 
                for(i=1;i<=NF;i++) {s+=$i; ss+=$i^2} 
                printf "%.1f %.1f %d\n", s/NF, sqrt((ss-s^2/NF)/(NF-1)), NF} ' file

1.5 0.7 2
2.5 0.7 2

对于计算的样本标准差,您需要保护单个观察(NF == 1)的情况。

答案 2 :(得分:1)

复杂xmlstarlet + awk解决方案:

xmlstarlet ed -u "//fulldata/value" -x "concat(.,',')" add.xml \
| xmlstarlet sel -B -t -v "//fulldata" -n \
| awk -F, '{ n=NF-1; sum=sq=0; for(i=1;i<=n;i++) { sum+=$i; sq+=$i^2 }
  printf "%.1f\n%.1f\n%d\n", sum/n, sqrt((sq-sum^2/n)/(n-1)), n }'

输出:

1.5
0.7
2
2.5
0.7
2