使用bash基于一行

时间:2016-04-25 03:51:18

标签: bash awk sed

输入如下

A  20  240
A  15  150
B  65  210
B  80  300
C  90  400
C  34  320

对于每个类别(在第1栏中标记为A,B,C ......),我想找到最小数量和最大数量(最大范围)。所以期待看到:

A  15  240
B  65  300
C  34  400

那我该如何使用bash?

2 个答案:

答案 0 :(得分:2)

使用awk:

awk '
    !($1 in min) { min[$1] = $2; max[$1] = $3; next }
    {
        min[$1] = ( $2 < min[$1] ? $2 : min[$1] )
        max[$1] = ( $3 > max[$1] ? $3 : max[$1] )
    } 
    END {
        for(x in min) print x, min[x], max[x]
}' file
A 15 240
B 65 300
C 34 400

我们迭代每一行,并将最小值和最大值分配给以第一列为键的地图。在END块中,我们迭代哈希并从两个映射中打印出键和值。

答案 1 :(得分:0)

我试图在awk中对未设置变量的副作用做出另一种解决方案(作为解决方法)。 (可能会对此进行更优化。)

cat min_max

#!/bin/bash
awk '
    NF!=3 || $2 $3 ~ "[^0-9-]" {next;}           # short filter
    min[$1]=="" {min[$1]=$2; max[$1]=$3; next;}  # first occur a given ID--> set min&max,read nxt ln
    min[$1]>$2  {min[$1]=$2;}                    # other occur IDs--> refresh min if required
    max[$1]<$3  {max[$1]=$3;}                    # refreshing max if required 
    END {for(x in min)printf("%-2s %5d %5d\n", x, min[x], max[x]);}
' $1

cat in4

A  20  240
B  65  210
C  90  400
A  15  150
C  34  320
E  -30  -20
D   0  100
B  80  300
D  10   90
E  -20 -10

./ min_max in4

A     15   240
B     65   300
C     34   400
D      0   100
E    -30   -10

此bash代码生成相同的内容。

cat min_max2

#!/bin/bash
(($#!=1))&& { echo "Usage $0 inpfile"; exit 1; }
declare -A min max                                   # define associative arrays
while read id mn mx; do
   [[ ${min[$id]+any} == "" ]] && { min[$id]=$mn; max[$id]=$mx; continue; } # parameter extension
   (( ${min[$id]} > $mn )) && min[$id]=$mn
   (( ${max[$id]} < $mx )) && max[$id]=$mx
done <$1
for i in ${!min[@]}; do printf "%-2s %5d %5d\n" $i ${min[$i]} ${max[$i]}; done