Ich möchte zählen, wie oft die verschiedenen Susbtrings in einer Reihe von Zeichenfolgen in der 2. Spalte einer Tab-Datei angezeigt werden. Auf diese Weise mache ich eine Aufteilung, um jeden Teilstring zu trennen und dann zu zählen. Funktioniert jedoch nicht richtig.

Die Eingabe ist wie

rs12255619 A/C chr10    AA AA AC AA AA AA AA AA AA AC AA
rs7909677 A/G chr10     AA AA AA AA AA AA AA AA AA AA AA

Die gewünschte Ausgabe

rs12255619 A/C chr10    AA AA AC AA AA AA AA AA AA AC AA   AA=9;AC=2
rs7909677 A/G chr10     AA AA AA AA AA AA AA AA AA AA CC   AA=10;CC=1

Und so weiter....

awk 'BEGIN {FS=OFS="\t"} {gf=split($2,gfp," ")} {for (i=1;i<=gf;i++){
                                      if (gfp[i]=="AA"){i++; printf $1FS$2FS"%s\n" i, gfp[i]}
                                      else if (gfp[i]=="AC" || gfp[i] == "CA"){i++; printf $1FS$2FS"%s"gfp[i]"="i";\n"}
                                                            }}' input > output

Und ich versuche auch, ein anderes Skript zu erstellen, aber ich denke, dass die Zählung jede Zählung so oft wiederholt, wie sie für jede Zeile stattfindet. Hier habe ich eine Aufteilung unter der ersten Aufteilung durchgeführt, um zwischen Teilzeichenfolgen zu unterscheiden

awk 'BEGIN {FS=OFS="\t"} {gf=split($2,gfp," ");} {for (i=1;i<=gf;i++){

                     par=gfp[i];
                     gfeach=split($2,gfpeach,par);
                     print par "=" gfeach[i]";"
                                              }
                      }' input > output

Ich bin mir sicher, dass es einige einfachere Möglichkeiten gibt, aber ich kann es nicht vollständig lösen. Ist dies in einer UNIX-Umgebung möglich? Danke im Voraus

1
Perceval Vellosillo Gonzalez 17 Apr. 2018 im 17:15

4 Antworten

Beste Antwort

Ihre Eingabe stimmt nicht mit Ihrer Ausgabe überein, also raten wir alle nur, aber dies könnte das sein, was Sie wollen:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
{
    delete cnt
    split($2,tmp,/ /)
    for (i in tmp) {
        str = tmp[i]
        cnt[str]++
    }

    printf "%s", $0
    sep = OFS
    for (str in cnt) {
        printf "%s%s=%d", sep, str, cnt[str]
        sep = ";"
    }
    print ""
}

Abhängig davon, was Ihre Eingabe wirklich ist, wird Folgendes ausgegeben:

$ cat file
rs12255619 A/C chr10    AA AA AC AA AA AA AA AA AA AC AA
rs7909677 A/G chr10     AA AA AA AA AA AA AA AA AA AA AA

$ awk -f tst.awk file
rs12255619 A/C chr10    AA AA AC AA AA AA AA AA AA AC AA        AA=9;AC=2
rs7909677 A/G chr10     AA AA AA AA AA AA AA AA AA AA AA        AA=11

$ cat file
rs12255619 A/C chr10    AA AA AC AA AA AA AA AA AA AC AA
rs7909677 A/G chr10     AA AA AA AA AA AA AA AA AA AA CC

$ awk -f tst.awk file
rs12255619 A/C chr10    AA AA AC AA AA AA AA AA AA AC AA        AA=9;AC=2
rs7909677 A/G chr10     AA AA AA AA AA AA AA AA AA AA CC        AA=10;CC=1
3
Ed Morton 17 Apr. 2018 im 14:37

Etwas wie das?

$ awk '{for(i=4;i<=NF;i++) c[$i]++; 
        for(k in c) {s=s sep k"="c[k]; sep=";"; c[k]=0} 
        $NF=$NF OFS s; s=sep=""}1' file | column -t

rs12255619  A/C  chr10  AA  AA  AC  AA  AA  AA  AA  AA  AA  AC  AA  AA=9;AC=2
rs7909677   A/G  chr10  AA  AA  AA  AA  AA  AA  AA  AA  AA  AA  AA  AA=11;AC=0

Beachten Sie, dass die erfassten Buchstaben zunehmend zunehmen, da nur die beobachteten Schlüssel bis zu einer Zeile gedruckt werden. Wenn Sie beispielsweise CC in der zweiten Zeile hatten, wird die Anzahl nicht in der ersten Zeile aufgeführt.

2
karakfa 17 Apr. 2018 im 14:27

Könnte es in Perl tun

perl -lpe '$a{$_}++ for /\b[A-Z]{2}\b/g;
           $_.=" ".join(";",map{"$_=$a{$_}"}keys%a);
           %a = map{$_=>0}keys%a' file

Produziert

rs12255619 A/C chr10    AA AA AC AA AA AA AA AA AA AC AA AA=9;AC=2
rs7909677 A/G chr10     AA AA AA AA AA AA AA AA AA AA CC AA=10;CC=1;AC=0

Für neue Anforderungen

perl -lpe '$a{$_}++ for /\b[A-Z]{2}\b/g;
           $_.=" ".join(";",map{"$_=$a{$_}"}keys%a);
           undef %a' file

Produziert

rs12255619 A/C chr10    AA AA AC AA AA AA AA AA AA AC AA AC=2;AA=9
rs7909677 A/G chr10     AA AA AA AA AA AA AA AA AA AA CC CC=1;AA=10
2
123 17 Apr. 2018 im 14:40
#!/bin/bash

strings="AA AC CC"

while read line; do
        echo -n "$line: "
        for name in $strings; do
                num=$(echo $line | xargs -n1 | grep -cw $name)
                if [[ $num -ne 0 ]]; then
                        echo -n "$name=$num;"
                fi
        done
        echo
done < inputFile.txt
-1
Alex Stiff 17 Apr. 2018 im 14:27