2016-04-25 89 views
-5

输入的一列是如下使用bash于集群基于一行

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

对于每个类别(标记为A,B,C..in第1列),我想找到最小值和最大值(作为最大范围)。所以期待看到:

A 15 240 
B 65 300 
C 34 400 

那么我怎么能使用bash?

+4

请告诉我们您已经尝试到目前为止 – sjsam

+0

读过书的有效AWK编程,第4版,由阿诺德·罗宾斯,然后有bash的通话AWK一旦你写琐碎awk脚本做什么那份工作。 –

回答

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

你刚刚提供了一个免费的编码服务 – sjsam

+3

...这是downvote的一个很好的理由? –

+1

社区提供应回答哪些问题的指导。免费的编码服务可能会鼓励用户不费吹灰之力回复问题,恐怕你也同意我的猜测。 – sjsam

0

我试图做一个其他解决方案(作为解决方法)awk中的未设置变量的副作用。 (可能是这是有点更优化。)

猫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 

猫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的代码产生一样。

猫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 
+1

谢谢@EdMorton。在我的输出中是一个''“”0 0“行,没有想到我把'delete min [”“]''。现在我知道它是由我的输入文件末尾多余的空白行引起的。现在我在脚本中添加一个简短的过滤器行。 –

+0

不客气,但这似乎不是必要的,因为OP几乎肯定在他/她的输入文件中没有空白或任何其他格式不正确的行。 –