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
4 Antworten
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
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.
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
#!/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
Verwandte Fragen
Neue Fragen
bash
Bei Fragen zu Skripten, die für die Bash-Befehlsshell geschrieben wurden. Überprüfen Sie Shell-Skripte mit Fehlern / Syntaxfehlern mit dem Shellcheck-Programm (oder auf dem Web-Shellcheck-Server unter https://shellcheck.net), bevor Sie sie hier veröffentlichen. Fragen zur interaktiven Verwendung von Bash sind bei Super User eher themenbezogen als bei Stack Overflow.