UNIX группа по двум значениям - PullRequest
0 голосов
/ 01 февраля 2019

У меня есть файл со следующими строками (значения разделены ";"):

dev_name;dev_type;soft
name1;ASR1;11.1
name2;ASR1;12.2
name3;ASR1;11.1
name4;ASR3;15.1

Я знаю, как сгруппировать их по одному значению, например, подсчет всех ASRx, но как мне это сделать?сгруппируйте его по двум значениям, например:

ASR1
    *11.1 - 2
    *12.2 - 1
ASR3 
    *15.1 - 1

Ответы [ 6 ]

0 голосов
/ 04 февраля 2019

Еще одно решение, использующее всегда полезную GNU datamash для подсчета групп:

$ datamash -t ';' --header-in -sg 2,3 count 3 < input.txt |
   awk -F';' '$1 != curr { curr = $1; print $1 } { print "\t*" $2 " - " $3 }' 
ASR1
    *11.1 - 2
    *12.2 - 1
ASR3
    *15.1 - 1
0 голосов
/ 01 февраля 2019

еще awk

$ awk -F';' 'NR>1 {a[$2]; b[$3]; c[$2,$3]++} 
             END  {for(k in a) {print k; 
                                for(p in b) 
                                   if(c[k,p]) print "\t*"p,"-",c[k,p]}}' file
ASR1
        *11.1 - 2
        *12.2 - 1
ASR3
        *15.1 - 1
0 голосов
/ 01 февраля 2019
$ cat tst.awk
BEGIN { FS=";"; OFS=" - " }
NR==1 { next }
$2 != prev { prt(); prev=$2 }
{ cnt[$3]++ }
END { prt() }

function prt(   soft) {
    if ( prev != "" ) {
        print prev
        for (soft in cnt) {
            print "    *" soft, cnt[soft]
        }
        delete cnt
    }
}

$ awk -f tst.awk file
ASR1
    *11.1 - 2
    *12.2 - 1
ASR3
    *15.1 - 1

Или, если вы любите трубы ....

$ tail +2 file | cut -d';' -f2- | sort | uniq -c |
    awk -F'[ ;]+' '{print ($3!=prev ? $3 ORS : "") "    *" $4 " - " $2; prev=$3}'
ASR1
    *11.1 - 2
    *12.2 - 1
ASR3
    *15.1 - 1
0 голосов
/ 01 февраля 2019

Использование Perl

$ cat bykub.txt
dev_name;dev_type;soft
name1;ASR1;11.1
name2;ASR1;12.2
name3;ASR1;11.1
name4;ASR3;15.1
$ perl -F";" -lane ' $kv{$F[1]}{$F[2]}++ if $.>1;END { while(($x,$y) = each(%kv)) { print $x;while(($p,$q) = each(%$y)){ print "\t\*$p - $q" }}}' bykub.txt
ASR1
        *11.1 - 2
        *12.2 - 1
ASR3
        *15.1 - 1
$
0 голосов
/ 01 февраля 2019

попробуйте что-то вроде

awk -F ';' '
   NR==1{next}
   {aRaw[$2"-"$3]++}
   END {
      asorti( aRaw, aVal)
      for( Val in aVal) {
         split( aVal [Val], aTmp, /-/ )
         if ( aTmp[1] != Last ) { Last = aTmp[1]; print Last }
         print "   " aTmp[2] " " aRaw[ aVal[ Val] ]
         }
      }
   ' YourFile

ключ здесь, чтобы использовать 2 поля в массиве.Часть END сложнее представить значение, чем сам контент

0 голосов
/ 01 февраля 2019

Я не хочу поощрять ленивые вопросы, но я написал решение, и я уверен, что кто-то может указать на улучшения.Я люблю размещать ответы на этом сайте, потому что я многому учусь.:)

Один двоичный подзвон к sort, иначе вся встроенная обработка.Это означает использование read, что медленно.Если ваш файл большой, я бы порекомендовал переписать цикл в awk или perl, но это сделает работу.

sed 1d groups |                        # strip the header
  sort -t';' -k2,3 > group.srt         # pre-sort to collect groupings
declare -i ctr=0                       # initialize integer record counter
IFS=';' read x lastA lastB < group.srt # priming read for comparators
printf "$lastA\n\t*$lastB - "          # priming print (assumes at least one record)
while IFS=';' read x a b               # loop through the file
do if [[ "$lastA" < "$a" ]]            # on every MAJOR change
   then printf "$ctr\n$a\n\t*$b - "    # print total, new MAJOR header and MINOR header
        lastA="$a"                     # update the MAJOR comparator
        lastB="$b"                     # update the MINOR comparator
        ctr=1                          # reset the counter
   elif [[ "$lastB" < "$b" ]]          # on every MINOR change
   then printf "$ctr\n\t*$b - "        # print total and MINOR header
        ctr=1                          # reset the counter
   else (( ctr++ ))                    # otherwise increment
   fi
done < group.srt                       # feed read from sorted file
printf "$ctr\n"                        # print final group total at EOF
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...