2016-08-16 4 views
2

ich eine PLINK ped-Datei, die wie folgt aussieht:UNIX - Count Vorkommen von Zeichen pro Zeile zwischen zwei Feldern und fügen neue Spalte mit

ACS_D132  ACS_D132  0  0  2  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1 
ACS_D140  ACS_D140  0  0  2  2  1 1  1 1  1 1  1 1  2 1  1 1  2 1  1 1 
ACS_D141  ACS_D141  0  0  2  2  2 1  1 1  1 1  1 1  1 1  1 1  1 1  2 1 
ACS_D147  ACS_D147  0  0  2  2  1 1  1 1  1 1  1 1  2 1  1 1  1 1  1 1 
ACS_D155  ACS_D155  0  0  1  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1 
ACS_D196  ACS_D196  0  0  2  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1 
ACS_D221  ACS_D221  0  0  2  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1 

Ich interessiere mich für das Zählen, wie viele Mal, wenn die Zeichenfolge „2 "tritt zwischen dem 7. Feld (eingeschlossen) und dem letzten Feld auf. Dann wird, wenn die Anzahl der Vorkommen ist:

  • 0: 1 hinzufügen (abwesend) in die neue letzte Feld

  • 1: 2 hinzufügen (vorhanden ist) auf die neue letzte Feld

  • 2: hinzufügen von 2 (anwesend) auf das neue letzte Feld

der Ausgang wäre:

ACS_D132  ACS_D132  0  0  2  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 
ACS_D140  ACS_D140  0  0  2  2  1 1  1 1  1 1  1 1  2 1  1 1  2 1  1 1  2 
ACS_D141  ACS_D141  0  0  2  2  2 1  1 1  1 1  1 1  1 1  1 1  1 1  2 1  2 
ACS_D147  ACS_D147  0  0  2  2  1 1  1 1  1 1  1 1  2 1  1 1  1 1  1 1  2 
ACS_D155  ACS_D155  0  0  1  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 
ACS_D196  ACS_D196  0  0  2  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 
ACS_D221  ACS_D221  0  0  2  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 

Ich weiß, dass das Auftreten einer Zeichenkette in jedem Feld kann ich zählen:

grep -n -o "2" file1 | sortieren -n | uniq -c | cut -d: -f 1

Und dass ich die 2 Ergebnisse mit fusionieren können:

Paste -d‘ 'file1 file2> file3

Aber ich weiß nicht, wie man die Vorkommen zwischen zwei Feldern zählt.

Vielen Dank im Voraus für Ihre Hilfe!

Antwort

1

Sie awk verwenden können, für Spalte, Zeile basierte Daten zu überprüfen:

awk '{c=0; for(i=7; i<=NF; i++) if ($i==2) c++; if (c<2) c++; print $0, c}' file 

ACS_D132  ACS_D132  0  0  2  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1 1 
ACS_D140  ACS_D140  0  0  2  2  1 1  1 1  1 1  1 1  2 1  1 1  2 1  1 1 2 
ACS_D141  ACS_D141  0  0  2  2  2 1  1 1  1 1  1 1  1 1  1 1  1 1  2 1 2 
ACS_D147  ACS_D147  0  0  2  2  1 1  1 1  1 1  1 1  2 1  1 1  1 1  1 1 2 
ACS_D155  ACS_D155  0  0  1  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1 1 
ACS_D196  ACS_D196  0  0  2  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1 1 
ACS_D221  ACS_D221  0  0  2  1  1 1  1 1  1 1  1 1  1 1  1 1  1 1  1 1 1 
1

Perl zur Rettung:

perl -ape 's/$/" " . (1 + !! grep 2 == $_, @F[6 .. $#F])/e' 
  • -p liest die Eingangs Zeile für Zeile und druckt das Ergebnis
  • -a spaltet jedes Leitungseingang auf Leerzeichen in die @F Array
  • grep in skalare context gibt die Anzahl zurück, durch !! (doppelte Verneinung) wir ändern es zu 0 oder 1, und indem wir 1 hinzufügen, machen wir es zu 1 und 2 wie gefordert
  • s /// ersetzt $ (Ende der Zeile) mit dem Ergebnis des Codes im Ersatzteil (das ist, was/e tut)
+0

Das hat perfekt funktioniert! Danke für deine schnelle Antwort! – Svalf

1

Sie awk verwenden:

awk '{s=0;for(i=7;i<=NF;i++) if($i==2) s+=1; s=s==0?1:2; print $0, s;}' data.txt 

Erläuterungen:

  • Die Anweisungen zwischen dem {} sind auf jeder Zeile der Datei ausgeführt.
  • NF ist die Anzahl der Felder in der Zeile. Sie sind von 1 bis NF nummeriert und Sie können auf sie mit der $ n Notation zugreifen.
Verwandte Themen