SED, AWK, GREP AUFGABE

Post Reply
Message
Author
hardia
Posts: 15
Joined: 04. Mar 2014 10:00

SED, AWK, GREP AUFGABE

#1 Post 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
Last edited by hardia on 05. Mar 2014 11:06, edited 1 time in total.

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#2 Post 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
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

hardia
Posts: 15
Joined: 04. Mar 2014 10:00

#3 Post 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 ;-)

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#4 Post 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
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

hardia
Posts: 15
Joined: 04. Mar 2014 10:00

#5 Post 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 :-)

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#6 Post 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
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

hardia
Posts: 15
Joined: 04. Mar 2014 10:00

#7 Post 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

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#8 Post by Janka »

Ich bin gespannt.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

hardia
Posts: 15
Joined: 04. Mar 2014 10:00

#9 Post 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 :-)

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#10 Post 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
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

Post Reply