文本文件列上的算术运算

时间:2019-05-03 07:11:44

标签: linux bash ubuntu

我的文本文件中有四列。我需要获取与第二列相对应的第四列的平均值,然后将输出保存到另一个文件中,该文件将仅包含具有平均结果的两列。请帮助

ABC DEF IGK LMN
21  56700   001000  -98.3
24  56700   002000  -96.3
6   56700   003000  -93.8
9   56700   004000  -47.3
21  56700   005000  -58.3
36  56700   006000  -78.3
21  56701   001000  -98.3
28  56701   002000  -98.3
21  56701   003000  -99.3
20  56701   004000  -58.3
21  56701   005000  -99.3
10  56701   006000  -98.3
2   56701   007000  -87.3
2   56701   008000  -57.3
21  56702   001000  -63.3
1   56702   002000  -67.3
17  56702   003000  -47.3
21  56702   004000  -73.3
13  56702   005000  -60.3
10  56702   006000  -90.3
14  56702   007000  -77.3
11  56702   008000  -97.3
10  56702   009000  -98.3
13  56702   010000  -87.3
17  56702   011000  -77.3
11  56702   012000  -68.3

预期输出:

DEF Average of LMN
56700   -78.71666667
56701   -87.05
56702   -75.63333333

我可以使用以下方法一次性获得第四列的总体平均值:

awk '{total+= $4} END {print total/NR}' inputfilename.txt

但是我需要申请一个条件。

3 个答案:

答案 0 :(得分:1)

使用两个数组,一个用于求和;一个用于计数添加到其中的数字。在文件末尾打印DEF和相应的平均值。

awk 'NR>1{count[$2]++;total[$2]+=$4} END{for(key in count) print key, total[key]/count[key]}' file

注意: NR>1用于排除标题行,如果实际输入没有标题行,只需将其删除即可。

给出示例,其输出如下:

56700 -74.8
56701 -87.05
56702 -75.6333

然后,如果需要,您可以使用sort对输出进行排序。

答案 1 :(得分:0)

您还可以考虑使用更强大的语言,特别是在您需要做更多花哨的事情时。

例如7 in Fruit.__members__.values()

@objc func handleTap(rec: UITapGestureRecognizer){

    if rec.state == .ended {
        let location: CGPoint = rec.location(in: sceneLocationView)
        let hits = self.sceneLocationView.hitTest(location, options: nil).filter { $0.node.name != nil }
        if !hits.isEmpty{

            let tappedNode = hits.first?.node
            print("NODE TAPPED", tappedNode?.name)
        }
    }
}

答案 2 :(得分:0)

因为您的原始标签包含bash,下面是一个bashbc-工具的示例(不是单行代码,但有时希望学习bash):

# only if needed in a short variable, later possible to test if exist, readable, ...
in=/path/to/your/testfile.txt
# we build a loop over your keys, possible
#  - for fixed length files and a fixed byte position
#    cut -b 5-10 
#  - for variable blocked with one (ore more) spaces as delimiter
#    sed -e 's/  */ /g' | cut -d ' ' -f 2   
for key in $(cat $in | cut -b 5-10 | sort -u) ; do
  # initialize counter for summary and number of elements per key
  s=0; a=0
  # grep all your relevant data from your inputfile (only for the key)
  # depends on your data you can grep on bytes (here from start of line with 4
  # characters and from byte 5-10 with your key)
  for x in $(grep -E "^.{4}${key}" $in | sed -e 's/  */ /g' | cut -d' ' -f4) ; do
    # count sum and add 1 to the number of entries
    s=$(echo "$s+$x" | bc --mathlib)
    ((a++))
  done
  # now print your key (as integer) and avg (as float with 6 decimals)
  printf "%i %.6f\n" $key $(echo "$s/$a" | bc --mathlib)
done
与参数bc一起使用的

--mathlib使用20的小数位。如果需要或需要,可以使用更高的小数位并仅在打印结果时减小小数位。

只有当输入文件的行号不是很大(我不使用此示例数百万行)时,这种带有两个循环(一个用于键,另一个用于每个键)的解决方案是可以接受的。作为一些单行代码(尤其是对于初学者)。