Contare le linee tra “X” s


13

Voglio contare le linee tra "X" s. Questo è solo un esempio; Devo applicare il codice a un risultato biologico complesso. Sarò grato se puoi suggerire qualche comando, preferibilmente usando awk, grepo sedcome ho familiarità con quelli.

Esempio:

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

Uscita desiderata:

3
4
1

2
Potresti essere interessato a Bioinformatica se lavorerai in questo campo.
terdon,

Risposte:


13

Con awk:

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

3
4
1

Incrementa un conteggio per ogni riga che non contiene X; stampa e reimposta il conteggio delle righe contenenti X.


2
Se la prima riga non fosse an X, il primo numero di righe verrebbe comunque conteggiato ed emesso con questa soluzione, fino a quando la prima riga con Xviene abbinata. EX (Non è possibile aggiungere nuove righe nei commenti, ma considera che c'è una nuova riga tra ciascun personaggio; P): Y X Y Y X Y Y Ysarebbe in uscita:1 2
Dan

1
@muru questo non funzionerà se non ci fosse X alla fine (bisogno di aggiungere END{if (count)print count}), e producendo una linea vuota dove X era in inizio per evitare che tu possa aggiungere anche /X/&&countin condizione
αғsнιη

1
Eh. Un commento si lamenta che i primi Ynon dovrebbero essere contati perché non sono esattamente tra due Xsecondi; l'altro si lamenta che i messaggi finali Ynon vengono conteggiati perché non sono esattamente tra due Xsecondi. Aspetterò che l'OP chiarisca, se necessario; Sto bene con questa risposta com'è fino ad allora.
Muru,

12
$ awk '/X/ && prev{print NR-prev-1} /X/{prev=NR}' file
3
4
1

Come funziona:

Awk legge implicitamente i file di input riga per riga.

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

    Per ogni riga che contiene Xe se in precedenza è stato assegnato un valore prev, quindi stampare il numero della riga corrente NR, meno prevmeno uno.

  • /X/{prev=NR}

    Per ogni riga che contiene X, impostare la variabile prevper il numero di linea corrente, NR.


4
Eh, carino. L'abuso NRmi dà un'idea:awk '/X/{print NR - 1; NR = 0}' foo
muru

Grazie, mi dà le informazioni esatte. che è richiesto.
Rhea,

Muro: bello e difficile. Fatta eccezione per la stampa di un valore di troppo, funziona per me con gawk e mawk. Sono curioso di sapere se questo è un comportamento garantito. @EdMorton?
Giovanni 1024

3
@rhea A meno che la tua prima riga non sia sempre una X, c'è una piccola differenza nell'output tra le 2 risposte, come ho spiegato in un commento sotto la risposta di Muru.
Dan,

1
@ John1024 grazie! Spero che mi possa aiutare.
Rhea,

6

Un altro awkapproccio semplice che funziona con i dati di esempio di OP e se Xnon era nella prima o addirittura nelle ultime X o ripetute.

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

Quanto sopra è corretto quando c'è un solo campo in ogni riga con FS predefinito qualsiasi spazio bianco , altrimenti sotto è rivisto in generale per il conteggio lineare . È possibile inserire il PATTERN al posto di X lì.

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

Input di esempio:

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

L'output è:

3
1
2

1

La maggior parte delle risposte qui corrispondono al contenuto della riga da contare usando le espressioni regolari incorporate nel programma Awk. Se devi abbinare le righe al contenuto che può contenere caratteri speciali (sia in Awk che nelle espressioni regolari), sarebbe meglio confrontare effettivamente le stringhe per l'uguaglianza. Pertanto propongo il seguente script Awk come una variante della risposta di Muru :

BEGIN {
    count = 0;
}

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

Memorizzalo come file di testo, ad esempio count-rows.awk, e invocalo come segue:

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

Puoi adattare il valore needlea tuo piacimento. Il vantaggio di questo metodo è che puoi invocare il programma da uno script di shell con un valore arbitrario needlesenza problemi di escape:

awk -f count-rows.awk -v needle="$needle" input
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.