2013-09-24 29 views
0

我有特别令人讨厌的shell编程,在shell脚本中没有多少经验。我有以下文本文件。我需要做的是计算子集1的平均值Y(m)和子集2的平均值Y(m)之间的差值。可以有两个以上的子集,但它足以计算子集之间的差异1和子集2.Shell脚本来计算两个不同子集的列之间的平均值

我尝试了各种awk命令,但似乎我的大脑被太多的障碍炸了。 Arghhh!

MODEL PARAMETERS : 
Project : Report 
Dataset : xxx 

Number of subsets : 2 
Total number   : 8 

Subset number : 1 
Subset name  : xxx_sub1 
Number   : 4 

NR TYPE      X(m)  Y(m) Z(m) Volume Pressure CluNo  Activ Group 
--- --------------------- ------ ------ ----- ------- -------- -----  ----- ------ 
    1 Type text     0.00 -10.40 9.00 2000.0 500.0  0  0  1 
    2 Type text     0.00  -9.60 9.00 1000.0 500.0  0  1  1 
    3 Type text     3.00 -10.40 9.00 1200.0 500.0  1  1  1 
    4 Type text     3.00  -9.60 9.00 800.0 500.0  1  1  1 

Subset number : 2 
Subset name  : xxx_sub2 
Number   : 4 

NR TYPE      X(m)  Y(m) Z(m) Volume Pressure CluNo Activ Group 
--- --------------------- ------ ------ ----- ------- -------- ----- ----- ------ 
    1 Type text     0.00  10.40 15.00 2000.0 500.0  0   0  1 
    2 Type text     0.00  9.60 15.00 1000.0 500.0  0  1  1 
    3 Type text     3.00  10.40 15.00 1200.0 500.0  1  1  1 
    4 Type text     3.00  9.60 15.00 800.0 500.0  1  1  1 

Units : 
    Coordinates  : meter 
    Volume   : cubic cm 
    Pressure   : pascal 

基本上我需要在第一组Y(M)值的平均值:(-10.4-9.6-10.4-9.6)/ 4 = -10m和平均第二组Y(m)值的哪是(10.4 + 9.6 + 10.4 + 9.6)/ 4 = 10m并计算两个平均值之间的差值为20m。

+2

'我尝试了各种awk命令,但是...'。你能详细说明你尝试了什么吗? – devnull

+2

预期产量是多少? –

+1

除符号外,Y(m)在子集#1和#2上具有相同的值。给出一个例子来计算,我们可以提取它。 – Jotne

回答

2

鉴于您的结构化文件,您可以更轻松地拿起Y(m)列并对它们进行求和。每个总和被存储在阵列a在关键是Subset number

$ awk 'NR>1{for(i=1;i<=$9;i++)a[$2]+=$(23+i*10+i);a[$2]/=$9}END{print a[2]-a[1]"m"}' RS='Subset number' file 
20m 

对于两个子集只是打印两者之间的不同在ENDa[1]-a[2]即子集1的总和减去子集2的总和。对于更多的子集只是遍历每个键并执行所需的计算。

+0

也许我应该补充说,子集并不总是4个项目。这可能有所不同。 :D – Cnoobplusplus

+0

也许我应该提到我的脚本动态地选择了长度,看到for循环的最大值是'$ 9'而不是4,而实际上'a [$ 2]/= $ 9'实际上我的脚本没有包含一个单独的4. –

4

它可以通过该脚本来完成(带GNU awk中测试时,上述输入):

#!/bin/bash 

gawk -- ' 
    BEGIN { 
     s = 0 
     r = 0 
    } 

    /^Subset number/ { 
     s = $4 
     r = 0 
    } 

    /Type text/ { 
     subset[s][r] = $5 
     r++ 
    } 

    END { 
     for (s in subset) { 
      subset_average[s] = 0 
      for (r in subset[s]) { 
       subset_average[s] += subset[s][r] 
      } 
      subset_average[s] /= length(subset[s]) 
     } 
     print subset_average[2] - subset_average[1] 
    } 
' 

它可以通过修改END块被适配成多个子集,以及,。

如果在您的示例中“类型文本”仅仅是实际数据的替代,那么数据行可以进行其他匹配。通过在一行的开头匹配数字来说,可能在空格之前。

+0

不错,这是使用'awk' + 1替代方法的正确方法。只需在'awk'中提示,您可以依赖所有变量被初始化为0,所以'BEGIN'块是冗余的。 –

+0

这看起来很安静。我需要它在一个大脚本中,所以在#!/ bin/sh中更喜欢它。 但是子集[s] [r]给我一个语法错误。 :( – Cnoobplusplus

+0

@Cnoobplusplus - 不!!!不要尝试在shell中做这样的事情,它不是在shell中创建的东西,最好的解析文本文件是awk发明的,并且具有所有的内建构造支持 –