ubuntuusers.de

Bedingungen in awk, um mehrere Zeilen zu vergleichen

Status: Gelöst | Ubuntu-Version: Ubuntu 16.04 (Xenial Xerus)
Antworten |

rasputin53

Anmeldungsdatum:
13. Oktober 2016

Beiträge: 4

Hallo zusammen,

ich bin blutiger Anfänger in Linux und Programmierung und habe ein Problem.

Ich habe einen Datensatz, der vereinfacht in etwa so aussieht:

1
2
3
4
5
6
7
8
9
Probe	Chr	Position
AAAAA1A	1	123
AAAAA2A	1	123
BBBBB1A	2	277791
BBBBB1B	2	277791
BBBBB2A	2	2794
CCCCC1B	X	12576
DDDDD1A	X	2321212
DDDDD2A	X	2321212

Was ich jetzt möchte, ist an 2 Bedingungen geknüpft. Ich versuche, auf eine Lösung mit awk zu kommen, hab es aber bisher nicht weit gebracht.

Das Ziel:

Wenn in 2 oder mehr Zeilen $2 und $3 denselben Wert haben (= dieselbe Position im Genom), soll die zweite Bedingung geprüft werden. Wenn in den betroffenen Zeilen nämlich die ersten 6 Zeichen in $1 nicht identisch sind, soll mir das Programm die betroffenen Zeilen ausgeben, damit ich sie speichern und weiterverarbeiten kann.

In diesem Beispiel müsste das Ergebnis sein, dass folgende Zeilen ausgegeben werden:

1
2
3
4
AAAAA1A	1	123
AAAAA2A	1	123
DDDDD1A	X	2321212
DDDDD2A	X	2321212

$2 und $3 sind identisch, $1 aber innerhalb der ersten 6 Zeichen unterschiedlich.

Ich hoffe, das war verständlich. Falls nicht, helfe ich gerne beim Verstehen. Außerdem weiß ich natürlich auch, dass das gleich mehrere Probleme in einem sind, aber ich bin natürlich auch dankbar für jeden Einzelschritt, der mich dem Ziel näher bringt.

Es wäre sehr hilfreich für mich, wenn mir jemand bei diesem Problem weiterhelfen kann.

Eine vereinfachte Variante wäre z.B.: wenn in 2 oder mehr Zeilen $2 und $3 identisch sind und $1 unterschiedlich ist sind, gib mir diese Zeilen aus.

Gruß

Bearbeitet von sebix:

Bitte verwende in Zukunft Codeblöcke, um die Übersicht im Forum zu verbessern!

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4453

Wohnort: Göttingen

Sieht nicht schön aus, sollte aber funktionieren:

awk '{a=d; b=e; c=f; d=$1;e=$2;f=$3; sub1=substr(a,1,6); sub2=substr(d,1,6); if (b==e && c==f && sub1!=sub2) print a" "b" "c" \n"d" "e" "f}' test.txt 

Den Dateinamen am Ende musst Du natürlich noch anpassen...

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Hi rasputin53,

erstmal herzlich willkommen hier auf dem Forum !

Meine 1. Frage wäre: sind die Zeilen in irgend einer Weise sortiert ?
- wenn ja, kann man ja einfach aufeinander folgende Zeilen vergleichen,
- wenn nein, wäre der einfachste Weg wahrscheinlich, über ein assoziatives Array zu gehen, wobei der Index einfach die Felder $2 und $3 wäre.

Jetzt müsste man mit diesem Ansatz weiter was basteln ... also:
- das 1. Feld des 1. Treffers in besagtem Array ablegen (bzw. den betreffenden Substring)
- und dann vergleichen, ob bei der aktuellen Zeile das 1. Feld anders aussieht.

Einige Fragen wären immer noch zu klären:
Was soll z.B. geschehen, wenn zwar der 1. und der 2. Treffer gleich, aber der 3. Treffer anders ist ?
- brauchst Du dann alle 3 Treffer, oder sollen (Teil-) Doubletten einfach nur übersprungen werden ? (das wäre nämlich ziemlich einfach)

Wie Substrings bei awk gehen, hat Dir mein Vorredner ja schon gezeigt. Ansonsten solltest Du sowieso unbedingt mal die awk - Einführung lesen.

LG,

track

rasputin53

(Themenstarter)

Anmeldungsdatum:
13. Oktober 2016

Beiträge: 4

Vielen Dank für die schnellen Antworten. Ich war in den letzten Tagen ziemlich beschäftigt, sonst hätte ich schon früher geantwortet.

@Doc_Symbiosis: Danke für diese recht einfache Lösung. Wenn ich das richtig verstehe, ist das sozusagen ein akw-Skript als one-liner. Es funktioniert im Prinzip genau so, wie du es geschrieben hast, auch für mein Problem. Hier meine funtionierende Variante für die tatsächlichen Daten:

1
awk -F ";" '{a=e; b=f; c=g; d=h; e=$8; f=$24; g=$25; h=$26; sub1=substr(a,1,6); sub2=substr(e,1,6); if (b==f && c==g && d<=h+5 && d>=h-5 && sub1!=sub2) print a"-" b"-" c"-" d "\n" e"-" f"-" g"-" h}' input.csv > output.csv

Die Spaltennummern sind anders als in der Beispieldatei und die Position im Genom hat noch eine Toleranz von +/- 5 bekommen, aber sonst ist alles nach demselben Muster.

@track: Dir auch vielen Dank. Da ich mit der Lösung von DocSymbiosis schon weitergekommen bin, bin ich nicht weiter auf deine Fragen eingegangen. Jedenfalls brauche ich nur die Zeilen, in denen alle Bedingungen erfüllt sind.

Bearbeitet von rklm:

Codeblock. Bitte schau Dir mal Forum/Syntax an. Referenzen mit @ gibt es nicht in der Forensoftware, Du fügst besser [user:username:] ein.

Antworten |