
Ich habe diesen interessanten Befehl gefunden:
grep -v '^>' test.fasta | tr -d '\n' | sed -e 's/\(.\)/\1\n/g' | sort | uniq -c | sort -rn
Ich verstehe ungefähr, was es bedeutet (es zählt Buchstaben aus einer Textdatei), aber meine Frage betrifft Folgendes:
sed -e 's/\(.\)/\1\n/g'
Ich weiß, dass es aus drei Ersetzungsbefehlen besteht. Einer ersetzt neue Zeilen ( \n
), einer passt zu allen Zeichen außer Zeilenumbrüchen ( \(.\)
), aber ich bin ratlos /\1\
.
Antwort1
Der Befehl
sed -e 's/\(.\)/\1\n/g'
ist ein einzelner GNU- sed
Ersetzungsbefehl, der jedes Zeichen durch sich selbst ersetzt, gefolgt von einem Zeilenumbruchzeichen. Dies bewirkt, dass die Eingabe in eine einzelne Spalte mit einzelnen Zeichen zusammengefasst wird.
$ echo hello | sed -e 's/\(.\)/\1\n/g'
h
e
l
l
o
Dies \(.\)
ist eine „Erfassungsgruppe“, die ein einzelnes Zeichen erfasst. Dies \1
ist ein „Rückverweis“ auf die erste Erfassungsgruppe. Die Verwendung \1
im Ersetzungstext würde alles einfügen, was von der ersten Klammer erfasst wurde.
Es könnte auch ohne so viele Backslashes geschrieben werden wie
sed 's/./&\n/g'
wobei „wobei &
“ einfach „alles, was mit dem Ausdruck übereinstimmt“ bedeutet.
Der sed
Befehl erfordert GNU, sed
da dieser Standard sed
keine Zeilenumbrüche einfügen kann \n
.
Um dies mit Standardwerkzeugen effizienter zu erledigen, verwenden Sie
fold -w 1
stattdessen. Dies ist effizienter, da kein regulärer Ausdrucksabgleich für jedes Zeichen in der Eingabe erforderlich ist.
Mit fold
könnte Ihre Pipeline wie folgt geschrieben werden:
grep -v '^>' file | tr -d '\n' | fold -w 1 | sort | uniq -c | sort -rn
Alternativ können Sie awk
einige Schritte dieser Pipeline eliminieren,
awk '!/^>/ { for (i = 1; i <= length; ++i) count[substr($0,i,1)]++ }
END { for (ch in count) print count[ch], ch }' file |
sort -rn
Der awk
Code zählt, wie oft jedes Zeichen gesehen wurde. Dies geschieht, indem der Wert im Array erhöht wird, count
der jedem Zeichen im Eingabestrom entspricht. Am Ende der Eingabe wird eine Zusammenfassung der Zählungen und gezählten Zeichen ausgegeben.
Antwort2
Ich hoffe, das macht es klarer.
„Ich weiß, dass es sich um drei Ersatzbefehle handelt“
Es handelt sich lediglich um einen Ersatzbefehl (falls Sie den Befehl meinen sed
): s/<pattern to search>/<replacement>/
, der Folgendes ausführt:
- Suchen Sie für jede Zeile nach
<pattern>
und ersetzen Sie sie durch<replacement>
. - Die
g
Flagge bedeutetTu esGglobal, da standardmäßigsed
nur das erste Vorkommen von ersetzt wird<pattern>
.
"aber ich bin verloren bei
/\1\
"
Sie können ein Muster erfassen, indem Sie es mit Escape-Klammern \(<pattern>\)
oder nur Klammern mit der -E
Option umgeben (<pattern>)
.
Im <replacement>
Abschnitt wird dieses erfasste Muster durch einen Backslash und eine Nummer referenziert \<number>
. Die Nummer bezieht sich auf die Position der Erfassung, da es mehrere geben kann:
sed -E '/(<first capture>)(<second capture>)/\1\2/'
Der Befehl sed -e 's/\(.\)/\1\n/g'
bedeutet also:
- Erfassen Sie jedes Zeichen
\(.\)
und ersetzen Sie es durch sich selbst und eine neue Zeile\1\n
. - Machen Sie es mit
g
global und hören Sie nicht beim ersten Vorkommen auf.
Zum Beispiel:
$ echo foo | sed -E 's/(.)/\1\n/g'
f
o
o
Die -e
Optionen sind hier nicht erforderlich, es sei denn, Sie verketten mehrere sed
Befehle: sed -e '...' -e '...'
usw.
Weitere Informationen finden Sie unterRückverweise und Unterausdrücke.
Antwort3
Verwenden von Raku (früher bekannt als Perl_6)
raku -e 'for lines.grep({ !/ ^ \> / }).join { .say for .comb.Bag.sort(*.values).reverse};'
Beispieleingabe:
>sp|P01308|INS_HUMAN Insulin OS=Homo sapiens OX=9606 GN=INS PE=1 SV=1
MALWMRLLPLLALLALWGPDPAAAFVNQHLCGSHLVEALYLVCGERGFFYTPKTRREAED
LQVGQVELGGGPGAGSLQPLALEGSLQKRGIVEQCCTSICSLYQLENYCN
Beispielausgabe:
L => 20
G => 12
A => 10
E => 8
Q => 7
P => 6
C => 6
V => 6
R => 5
S => 5
Y => 4
F => 3
T => 3
N => 3
M => 2
D => 2
K => 2
I => 2
W => 2
H => 2
Der von Ihnen präsentierte Code kann in einer Reihe von Sprachen (nicht nur sed
) geschrieben sein, von denen jede Ihnen gefallen könnte. Ihr Code oben wurde beispielsweise in Raku, einem Mitglied der Perl-Sprachfamilie, neu geschrieben.
Der Großteil des Raku-Codes sollte ziemlich selbsterklärend sein: lines
werden eingelesen und grep
mit -ped versehen, wenn am Zeilenanfang kein „Größer-als“-Winkel !
vorhanden ist , und mit -ed versehen. Verbundene Zeilen werden mit -ed (in einzelne Zeichen aufgeteilt), -ged (jedes vorhandene Zeichen wird zu einem und Vorkommen werden als gezählt/aufgezeichnet ), -ed , um die höchste Anzahl von Vorkommen zuerst zu platzieren, und dann mit gedruckt .^
>
join
comb
Bag
key
values
sort
reverse
say