Mam plik tekstowy z wzorem, który wygląda następujące

Sample1
Feature 1
A
B
C
Feature 2
A
G
H
L
Sample2
Feature 1
A
M
W
Feature 2
P
L

Próbuję policzyć, ile wpisów dotyczy każdej funkcji w każdej próbce. Więc moja pożądana wydajność powinna wyglądać na coś takiego:

Sample1
Feature 1: 3
Feature 2: 4

Sample2
Feature 1: 3
Feature 2: 2

Próbowałem użyć następujących poleceń awk:

$ awk '{if(/^\Feature/){n=$0;}else{l[n]++}}
       END{for(n in l){print n" : "l[n]}}' inputfile.txt > result.txt

Ale dało mi następujące dane wyjściowe

Feature 1: 6
Feature 2: 6

Zastanawiałem się więc, czy ktoś może mi pomóc w modyfikowaniu tego polecenia, aby uzyskać pożądane wyjście lub sugerować dla mnie kolejne polecenie? (P.S oryginalny plik zawiera setki próbek i około 94 funkcji)

0
MonahAbouAlezz 4 czerwiec 2018, 11:14

3 odpowiedzi

Najlepsza odpowiedź

Możesz użyć tego awk:

awk '/^Sample/{printf "%s%s",(c?c"\n":""),$0;c=0;next}
     /^Feature/{printf "%s\n%s: ",(c?c:""),$0;c=0;next}
     {c++}
     END{print c}' file

Skrypt zwiększa licznik c tylko dla linii, które nie zaczynają się od Sample lub Feature.

Jeśli znaleziono jeden z 2 słów kluczowych, licznik jest drukowany.

1
oliv 4 czerwiec 2018, 16:13

To awk może również działać:

awk '/^Sample/ {
   for (i in a)
      print i ": " a[i]
   print
   delete a
   next
}
/^Feature/ {
   f = $0
   next
}
{
   ++a[f]
}
END {
   for (i in a) 
      print i ": " a[i]
}' file
Sample1
Feature 1: 3
Feature 2: 4
Sample2
Feature 1: 3
Feature 2: 2
0
anubhava 4 czerwiec 2018, 08:26
$ cat tst.awk
BEGIN { OFS = ": " }
/Sample/  { prtFeat(); print (NR>1 ? ORS : "") $0; next }
/Feature/ { prtFeat(); name=$0; next }
{ ++cnt }
END { prtFeat() }
function prtFeat() {
    if (cnt) {
        print name, cnt
        cnt = 0
    }
}

$ awk -f tst.awk file
Sample1
Feature 1: 3
Feature 2: 4

Sample2
Feature 1: 3
Feature 2: 2
0
Ed Morton 4 czerwiec 2018, 14:00