Aproveite a solução awk :
awk -F, '{ diff=$2-$3; if(a[$1]>diff || !a[$1]) { a[$1]=diff; b[$1]=$2 FS $3 } }
END{ for(i in a) print i,b[i] }' OFS=',' yourfile
A saída:
c1,5,3
c2,8,4
Eu quero imprimir as linhas distintas onde diff é mínimo. (diff = $ 2- $ 3)
O arquivo de entrada é:
c1,5,2 <-- diff=3
c1,5,3 <-- diff=2
c1,5,1 <-- diff=4
c2,8,3 <-- diff=5
c2,8,4 <-- diff=4
A saída esperada é:
c1,5,3
c2,8,4
Como posso fazer isso com Awk (por exemplo, com um one-liner)?
Em outras palavras, para cada primeiro valor de campo (c1, c2), desejo imprimir uma única linha com o primeiro valor de campo, escolhido para a diferença mínima entre o segundo e o terceiro campos.
Comando Awk de duas passagens, bastante sujo:
awk -F, 'FNR == NR {diff[NR] = $2-$3;
if (!($1 in minline) || diff[NR] < diff[minline[$1]]) {
minline[$1]=NR}; next}
FNR == 1 {for (a in minline) {p[minline[a]]}}
FNR in p' file.csv file.csv
Por interesse, aqui está como fazer isso usando SQL (feito no Postgres, para ser específico):
vagrant=# \d quick
Table "pg_temp_2.quick"
Column | Type | Modifiers
--------+---------+-----------
f1 | text |
f2 | integer |
f3 | integer |
vagrant=# select * from quick;
f1 | f2 | f3
----+----+----
c1 | 5 | 2
c1 | 5 | 3
c1 | 5 | 1
c2 | 8 | 3
c2 | 8 | 4
(5 rows)
vagrant=# select f1, f2, f3 from (select *, rank() over (partition by f1 order by f2 - f3) from quick) as x where rank = 1;
f1 | f2 | f3
----+----+----
c1 | 5 | 3
c2 | 8 | 4
(2 rows)
vagrant=#
Tags awk