Ich möchte grep verwenden, um alle Zeilen, die zwischen den Zeilen liegen, /protein_id=
bis zum Ende der angezeigten Proteinsequenz von einer Datei in eine andere zu kopieren. Zum Beispiel aus dieser Eingabe:
CDS 448..1269
/gene="nptII"
/note="neomycin phosphotransferase II"
/codon_start=1
/product="kanamycin resistance protein"
/protein_id="AAQ05967.1"
/db_xref="GI:33320494"
/translation="MAITLSATSLPISARIRAGSPAAWVERLFGYDWAQQTIGCSDAA
VFRLSAQGRPVLFVKTDLSGALNELQDEAARLSWLATTGVPCAAVLDVVTEAGRDWLL
LGEVPGQDLLSSHLAPAEKVSIMADAMRRLHTLDPATCPFDHQAKHRIERARTRMEAG
LVDQDDLDEEHQGLAPAELFARLKARMPDGEDLVVTHGDACLPNIMVENGRFSGFIDC
GRLGVADRYQDIALATRDIAEELGGEWADRFLVLYGIAAPDSQRIAFYRLLDEFF"
regulatory 1443..2148
Ich hätte gerne diese Ausgabe:
/protein_id="AAQ05967.1"
/db_xref="GI:33320494"
/translation="MAITLSATSLPISARIRAGSPAAWVERLFGYDWAQQTIGCSDAA
VFRLSAQGRPVLFVKTDLSGALNELQDEAARLSWLATTGVPCAAVLDVVTEAGRDWLL
LGEVPGQDLLSSHLAPAEKVSIMADAMRRLHTLDPATCPFDHQAKHRIERARTRMEAG
LVDQDDLDEEHQGLAPAELFARLKARMPDGEDLVVTHGDACLPNIMVENGRFSGFIDC
GRLGVADRYQDIALATRDIAEELGGEWADRFLVLYGIAAPDSQRIAFYRLLDEFF"
Beachten Sie, dass die Eingabe variieren kann, indem die Zeile, die mit beginnt, regulatory
durch etwas anderes ersetzt werden kann. Unveränderlich ist, dass die Sequenz in Großbuchstaben angegeben wird und mit einem endet "
. Ist dies mit grep möglich?
Antwort1
pcregrep
ist ein Grep-Dienstprogramm, das mit Perl 5 kompatible reguläre Ausdrücke verwendet. Reguläre Ausdrücke im Perl-Stil haben viele nützliche Funktionen, die die standardmäßigen POSIX-Ausdrücke nicht haben. Dies ist im Grunde dasselbe wie Grep, aber mit einer anderen Regexp-Syntax.
sudo apt-get install pcregrep
pcregrep -M .*'/protein_id=.*(\n|.)*\"' path/to/input-file
/protein_id
ist der Startsuchbegriff und "
ist der Endsuchbegriff.
Hier ist ein verallgemeinertes Beispiel für einen Befehl zum Ausführen einer mehrzeiligen Suche nach allen Zeilen, die zwischen einem Startsuchbegriff und einem Endsuchbegriff liegen:
pcregrep -M .*'START-SEARCH-TERM.*(\n|.)*END-SEARCH-TERM' path/to/SOURCE-FILE >> path/to/DESTINATION-FILE
Wo:
- SOURCE-FILE ist die Datei, die Ihre Daten enthält
- DESTINATION-FILE ist die Datei, in die die Ergebnisse kopiert werden
- START-SEARCH-TERM ist der Startsuchbegriff
- END-SEARCH-TERM ist der letzte Suchbegriff
-M, --multiline
Lassen Sie zu, dass Muster mit mehr als einer Zeile übereinstimmen.
Antwort2
Nein, grep
kann nicht über mehrere Zeilen hinweg abgeglichen werden. Sie könnten es mit tun, pcregrep
wie von @karel gezeigt, aber nicht rein grep
. Da Sie wissen, dass die Proteinsequenzen immer in GROSSBUCHSTABEN geschrieben sind und mit enden "
, könnten Sie stattdessen Folgendes abgleichen:
sed
sed -n '/\/protein_id=/,/^\s*[[:upper:]]\+"\s*$/{p}' two_seq.txt
Das
sed
Muster/foo/,/bar/{p}
bedeutet „drucke alle Zeilen zwischenfoo
und ausbar
“. Das-n
unterdrückt die normale Ausgabe, sodass nur die angeforderten Zeilen gedruckt werden. Beachten Sie, dass das von/
maskiert/protein_id=
werden muss (\/
), da das/
Teil des Übereinstimmungsoperators ist. Das zweite Muster ist etwas komplexer, es sucht nach 0 oder mehr Leerzeichen am Anfang der Zeile (^\s*
), dann nach einem oder mehreren Großbuchstaben, gefolgt von einem doppelten Anführungszeichen ([[:upper:]]"
) und dann nach 0 oder mehr Leerzeichen bis zum Ende der Zeile (\s*$
).Perl
perl -ne 'print if m#/protein_id=# ... m#[A-Z]+"\s*$#' file.flat
Hier gilt das gleiche Prinzip: Der
...
Bediener gibt einen Bereich an und die Linien zwischen den beiden Mustern werden gedruckt.awk
awk '/\/protein_id=/{a=1}; a==1{print} /^\s*[[:upper:]]+"\s*$/{a=0}' file.flat
Hier setzen wir die Variable auf ,
a
wenn1
die Zeile mit dem ersten Muster übereinstimmt, und auf ,0
wenn sie mit dem letzten übereinstimmt. Dann weisen wir an,awk
zu drucken, wenna
es ist1
. Da „print
is“ aufgerufen wird, bevor es für das zweite Mustera
auf gesetzt wird0
, wird hiermit auch die Zeile mit dem zweiten Muster eingeschlossen.