Zählen Sie die Zeilen zwischen "X"

13

Ich möchte die Zeilen zwischen "X" zählen. Dies ist nur ein Beispiel. Ich muss den Code auf ein komplexes biologisches Ergebnis anwenden. Ich bin dankbar , wenn Sie einen Befehl vorschlagen kann, vorzugsweise unter Verwendung von awk, grepoder sedwie ich bin mit denen.

Beispiel:

X
Y
Y
Y
X
Y
Y
Y
Y
X
Y
X

Gewünschte Ausgabe:

3
4
1
Rhea
quelle
2
Sie könnten an Bioinformatik interessiert sein, wenn Sie in diesem Bereich arbeiten.
Terdon

Antworten:

13

Mit awk:

$ awk '!/X/{count++}/X/{print count; count = 0}' input

3
4
1

Erhöhen Sie die Anzahl für jede Zeile, die nicht enthält X. Drucke und setze die Anzahl der Zeilen zurück, die enthalten X.

muru
quelle
2
Wenn die erste Zeile keine war X, würde die erste Anzahl von Zeilen mit dieser Lösung immer noch gezählt und ausgegeben, bis die erste Zeile mit Xübereinstimmt. EX (Es können keine neuen Zeilen in den Kommentaren hinzugefügt werden, es muss jedoch eine neue Zeile zwischen den einzelnen Zeichen stehen. P): Y X Y Y X Y Y Ywürde Folgendes ausgeben:1 2
Dan
1
@muru Das wird nicht funktionieren , wenn es keine X am Ende (Notwendigkeit addiert END{if (count)print count}) und Leerzeile produziert , wobei X in Start war zu vermeiden , die Sie hinzufügen können /X/&&countauch in Zustand
αғsнιη
1
Heh. Ein Kommentar beklagt, dass führende Ys nicht gezählt werden sollten, da sie nicht genau zwischen zwei Xs liegen. der andere beklagt, dass abschließende Ys nicht gezählt werden, weil sie nicht genau zwischen zwei Xs liegen. Ich werde warten, bis das OP geklärt ist, falls erforderlich. Mir geht es gut mit dieser Antwort, wie es bis dahin ist.
muru
12
$ awk '/X/ && prev{print NR-prev-1} /X/{prev=NR}' file
3
4
1

Wie es funktioniert:

Awk liest implizit die Eingabedateien Zeile für Zeile durch.

  • /X/ && prev{print NR-prev-1}

    Für jede Zeile, die enthält Xund der wir zuvor einen Wert zugewiesen haben prev, drucken Sie die Nummer der aktuellen Zeile aus NR, minus prevminus eins.

  • /X/{prev=NR}

    XSetzen Sie für jede Zeile, die enthält , die Variable prevauf die aktuelle Zeilennummer NR.

John1024
quelle
4
Na schön. Missbrauch NRbringt mich auf eine Idee:awk '/X/{print NR - 1; NR = 0}' foo
muru
Danke, es gibt mir die genauen Infos. welches benötigt wird.
Rhea
Muro: Nett und trickreich. Mit der Ausnahme, dass ein Wert zuviel gedruckt wird, funktioniert es bei mir unter Gawk und Mawk. Ich bin gespannt, ob dies ein garantiertes Verhalten ist. @EdMorton?
John1024
3
@rhea Wenn Ihre erste Zeile nicht immer eine ist X, gibt es einen kleinen Unterschied in der Ausgabe zwischen den beiden Antworten, wie ich in einem Kommentar unter der Antwort von muru erklärt habe.
Dan
1
@ John1024 danke! Ich hoffe es wird mir helfen.
Rhea
6

Ein weiterer einfacher awkAnsatz, der mit den Beispieldaten von OP funktioniert und bei dem Xes sich nicht um das erste oder sogar das letzte oder wiederholte X handelt.

awk -v RS='X' 'NF{print NF}' infile

Oben ist richtig, wenn in jeder Zeile nur ein Feld mit Standard-FS- Leerzeichen vorhanden ist. Andernfalls wird unten im Allgemeinen die Zeilenweise- Zählung überarbeitet . Sie können dort Ihr MUSTER anstelle von X eingeben .

awk -F'\n' -v RS='X' 'NF>2{print NF-2}'

Beispieleingabe:

X
Y YYY Y
YY
YY Y YY YY Y Y
X
Y Y Y
X
Y
Y
X
X

Die Ausgabe ist:

3
1
2
αғsнιη
quelle
1

Die meisten Antworten hier stimmen mit dem Inhalt der zu zählenden Zeile überein, wobei reguläre Ausdrücke verwendet werden, die in das Awk-Programm eingebettet sind. Wenn Sie Zeilen mit Inhalten abgleichen müssen, die Sonderzeichen enthalten (entweder mit Awk oder regulären Ausdrücken), ist es besser, Zeichenfolgen tatsächlich auf Gleichheit zu vergleichen. Deshalb schlage ich das folgende Awk-Skript als Variante von Murus Antwort vor :

BEGIN {
    count = 0;
}

{
    if ($0 == needle) {
        if (count) {
            print count;
            count = 0;
        }
    } else {
        count++;
    }
}

Speichern Sie es zB als Textdatei count-rows.awkund rufen Sie es wie folgt auf:

awk -f count-rows.awk -v needle=X input

Sie können den Wert needlenach Ihren Wünschen anpassen . Der Vorteil dieser Methode ist, dass Sie das Programm aus einem Shell-Skript mit einem beliebigen Wert aufrufen können, needleohne Probleme zu umgehen:

awk -f count-rows.awk -v needle="$needle" input
David Foerster
quelle