SED, AWK, GREP AUFGABE

Antworten
Nachricht
Autor
hardia
Beiträge: 15
Registriert: 04. Mär 2014 10:00

SED, AWK, GREP AUFGABE

#1 Beitrag von hardia » 04. Mär 2014 10:16

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
Zuletzt geändert von hardia am 05. Mär 2014 11:06, insgesamt 1-mal geändert.

Benutzeravatar
Janka
Beiträge: 3585
Registriert: 11. Feb 2006 19:10

#2 Beitrag von Janka » 04. Mär 2014 10:43

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
Beiträge: 15
Registriert: 04. Mär 2014 10:00

#3 Beitrag von hardia » 04. Mär 2014 11:37

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 ;-)

Benutzeravatar
Janka
Beiträge: 3585
Registriert: 11. Feb 2006 19:10

#4 Beitrag von Janka » 04. Mär 2014 12:32

Naja, ich würde es im ersten Schuss mit folgender regexp machen:

Code: Alles auswählen

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: Alles auswählen

$ 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: Alles auswählen

$ 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
Beiträge: 15
Registriert: 04. Mär 2014 10:00

#5 Beitrag von hardia » 04. Mär 2014 12:57

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 :-)

Benutzeravatar
Janka
Beiträge: 3585
Registriert: 11. Feb 2006 19:10

#6 Beitrag von Janka » 04. Mär 2014 13:55

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
Beiträge: 15
Registriert: 04. Mär 2014 10:00

#7 Beitrag von hardia » 04. Mär 2014 14:13

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

Benutzeravatar
Janka
Beiträge: 3585
Registriert: 11. Feb 2006 19:10

#8 Beitrag von Janka » 04. Mär 2014 15:30

Ich bin gespannt.

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

hardia
Beiträge: 15
Registriert: 04. Mär 2014 10:00

#9 Beitrag von hardia » 05. Mär 2014 10:48

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: Alles auswählen

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: Alles auswählen

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: Alles auswählen

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 :-)

Benutzeravatar
Janka
Beiträge: 3585
Registriert: 11. Feb 2006 19:10

#10 Beitrag von Janka » 05. Mär 2014 13:46

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.

Antworten