Page 1 of 1

SED, AWK, GREP AUFGABE

Posted: 04. Mar 2014 10:16
by hardia
Hallo, kann einer diese Aufgabe mit sed awk oder grep lösen?
Ich komm nicht dahinter :-)

#Textfile

CCGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAG



Aufgabe für Profis
a) Sie haben eine lange Textzeile z.B.: CCGATGCCCACCTAAGCAATGCCAGACTAACC
In dieser Textzeile sollen sie alle Vorkommen die mit ATG beginnen
und mit TAA,TGA oder TAG enden durch ein # ersetzen.
z.B.: CCG#GCA#CC
Zur Lösung dürfen nur grep, sed und awk verwendet werden.
b) Die Zeichen die zwischen ATG und TAA,TGA oder TAG vorkommen müssen im
Triplet auftreten. ATG ... TGA

Posted: 04. Mar 2014 10:43
by Janka
Contest-Aufgabe? Es wäre eine große Höflichkeit, den Contest zu verlinken.

Ansonsten geht das einfach mit sed 's/regexp/#/g;', wobei man die regexp selbst entwickeln muss. Aber auch das ist nicht sooo schwer.

Janka

Posted: 04. Mar 2014 11:37
by hardia
Hi Janka, na das ist doch schon was, ist eine Aufgabe innerhalb des LPI den ich grade mache. Die Regex würden mich ja auch noch interessieren ;-)

Posted: 04. Mar 2014 12:32
by Janka
Naja, ich würde es im ersten Schuss mit folgender regexp machen:

Code: Select all

Match: ATG(...)*?(TAA|TGA|TAG)
Substitution: ATG#\2
Wenn du Hilfe brauchst, wie man darauf kommt, frag einfach.

Das Problem ist, dass man dafür den non-greedy Quantifier *? benötigt - und den können weder sed noch awk (grep scheidet sowieso aus, weil wir substituieren wollen).

Code: Select all

$ sed <<<"CGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAG" -r 's/ATG&#40;...&#41;*?&#40;TAA|TGA|TAG&#41;/ATG#\2/g;'
CGATG#TAG
Bäähhh.

Z.B. Tcl liefert ein besseres Ergebnis:

Code: Select all

$ tclsh <<<'regsub -all &#123;ATG&#40;...&#41;*?&#40;TAA|TGA|TAG&#41;&#125; &#123;CGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAGATGCCCTAAGCAATGCCTACGTAGTAATAG&#125; &#123;ATG#\2&#125; result ; puts $result'
CGATG#TAAGCAATG#TAGTAATAGATG#TAAGCAATG#TAGTAATAGATG#TAAGCAATG#TAGTAATAGATG#TAAGCAATG#TAGTAATAGATG#TAAGCAATG#TAGTAATAGATG#TAAGCAATG#TAGTAATAG
Sollte das ein Contest sein, verstehe ich die Einschränkung auf grep, sed, awk. Es soll schließlich schwer sein und die offensichtliche Lösung soll nicht funzen.

In einer LPI-Prüfung halte ich die Frage für hinterhältig. Ich würde mit der offensichtlichen Antwort kontern, dass man gefälligst Perl oder Tcl zu installieren habe oder das gefälligst auf einer Maschine macht, wo diese Programme installiert sind. Falls es dafür keine Punkte gibt, kann man sich diese Prüfung dahin schieben, wo keine Sonne hinfällt.

Janka

Posted: 04. Mar 2014 12:57
by hardia
Es ist ein Contest. Eine freiwillige Zusatzaufgabe. In der LPI Prüfung kommt sowas heftiges nicht vor.
Aber die herrangehensweise und wie man auf die Lösungsansätze kommt interessiert mich schon :-)

Posted: 04. Mar 2014 13:55
by Janka
Wie gesagt, allein mit regexes geht es nur mit non-greedy-Quantifiern. Wenn die nicht erlaubt sind, kommst du nicht umhin, mit awk zu programmieren - ist eine vollwertige Programmiersprache. Ob man allein mit seds Musterpuffer sowas wie non-greedy-Quantifiers simulieren kann habe ich noch nicht untersucht. Würde ich auch nicht tun, da besseres Werkzeug existiert.

Zur Regexp: Du willst auf alles matchen, was nach ATG kommt. Also muss die Regexp damit beginnen. Danach sollen die Zeichen immer in Tripletts kommen, also kann man nicht einfach .* benutzen, sondern muss das Triplet aus drei beliebigen Zeichen selbst zum Atom machen, das macht man mit den Klammern. Danach kommt ein Quantifier. *? bedeutet: beliebig oft, aber so wenig wie möglich. Das bedeutet in der Praxis, dass der Teil dahinter die Folge "beliebig oft" abbricht, und genau diese Abbruchbedingung brauchen wir ja. Dahinter kommt ein weiteres Atom, das wahlweise aus der Zeichenfolgen TAA, TGA oder TAG besteht. Die Substitution ist einfach: ATG# ist einfach ein Literal, wird so in das Ergebnis geschrieben. \2 bezieht sich auf das zweite Klammer-Atom. Hier gibt es ja drei Möglichkeiten, so dass wir nicht einfach TAA oder so schreiben können. Stattdessen wird an der Stelle das tatsächlich gefundene Atom eingesetzt.

Janka

Posted: 04. Mar 2014 14:13
by hardia
Hey super Janka, da hast du mir echt weitergeholfen. Danke! Morgen erhalte ich die offizielle Lösung mal sehen wie die ist. Poste ich dann

Gruß Hardia

Posted: 04. Mar 2014 15:30
by Janka
Ich bin gespannt.

Janka

Posted: 05. Mar 2014 10:48
by hardia
Hier kommt die Lösung.
Also erstmal kann man mit diesem Textstream nichts gescheites anfangen hab ich so verstanden, also soll man sich erstmal sinvolle Zusammenhänge, Worter raussuchen und unterteilen, hier mit leerzeichen

(Die Leerzeichen in dem sed code sind zu beachten)

Code: Select all

cat daten.txt | sed -r 's/ATG/ ATG/g; s/TAA/TAA /g; s/TGA/TGA /g; s/TAG/TAG /g' > datenout.txt
CCG ATGCCCTAA GCA ATGCCTACGTAG TAA TAG ATGCCCTAA GCA ATGCCTACGTAG TAA TAG ATGCCCTAA GCA ATGCCTACGTAG TAA TAG ATGCCCTAA GCA ATGCCTACGTAG TAA TAG ATGCCCTAA GCA ATGCCTACGTAG TAA TAG ATGCCCTAA GCA ATGCCTACGTAG TAA TAG

und dann die verarbeitung wie in der Aufgabe beschrieben

Code: Select all

cat datenout.txt | sed -r 's/ \<ATG&#40;&#91;A-Z&#93;&#123;3&#125;&#41;+&#40;TAA|TAG|TGA&#41; /#/g; s/ //g'

CCG#GCA#TAATAG#GCA#TAATAG#GCA#TAATAG#GCA#TAATAG#GCA#TAATAG#GCA#TAATAG

Komplett also

Code: Select all

cat daten.txt | sed -r 's/ATG/ ATG/g; s/TAA/TAA /g; s/TGA/TGA /g; s/TAG/TAG /g; s/ \<ATG&#40;&#91;A-Z&#93;&#123;3&#125;&#41;+&#40;TAA|TAG|TGA&#41; /#/g; s/ //g'
CCG#GCA#TAATAG#GCA#TAATAG#GCA#TAATAG#GCA#TAATAG#GCA#TAATAG#GCA#TAATAG

Man ist das bäähh :-)

Posted: 05. Mar 2014 13:46
by Janka
Stimmt, mit Einfügung von Spezialzeichen (Leerzeichen) wird es auch funzen. Ansonsten entspricht die Lösung der mit den non-greedy Quantifiern.

Janka