Estrarre righe di testa usando lista

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
genomic
Prode Principiante
Messaggi: 5
Iscrizione: mercoledì 15 marzo 2017, 14:59
Desktop: ubuntu
Distribuzione: Ubuntu 14.04.1 LTS
Sesso: Maschile

Estrarre righe di testa usando lista

Messaggio da genomic »

Salve a tutti,
avrei un quesito da sottoporre ovvero ho un file di testo file.txt che ha una struttura come la seguente

>gi|103485499|ref|YP_615060.1| chromosomal replication initiation protein [Sphingopyxis alaskensis RB2256]
MSGDAAALWPRVAEGLRRDLGARTFDHWLKPVRFADYCALSGVVTLETASRFSANWINERFG
>gi|103485500|ref|YP_615061.1| glutathione S-transferase-like protein [Sphingopyxis alaskensis RB2256]
MKLFIGNKAYSSWSLRGWLAARHSGLPFEEVTVPLYNEEWNQRREGDEFAPSGGKVPILWDG
>gi|103485501|ref|YP_615062.1| ribosome biogenesis GTP-binding protein YsxC [Sphingopyxis alaskensis RB2256]
MSEIELEPGADPERAERARKLFSGPIAFLKSAPALQHLPVPSVPEIAFAGRSNVGKSSLLNALTN
>gi|103485502|ref|YP_615063.1| putative inner membrane protein translocase component YidC [Sphingopyxis alaskensis RB2256]
MDDKRNLIAAILLSVAILIGWNFVAERFFPTPDQPDVTKTVAGANGAPATAPTAQGQPSALPAPT

in questo file ad ogni header (identificato dal segno >) corrisponde una seconda riga con una sequenza di lettere. Il file che intendo processare presenta migliaia di header e sequenze. All'interno dell'Header è presente un codice univoco YP_615060.1, YP_615061.1 etc... che identifica la sequenza stessa.
Ho anche un secondo file chiamato lista.txt all'interno del queale sono elencati centinaia di codici univoci di mio interesse disposti uno per riga.
Quello che vorrei fare è estrarre, all'interno delle miglia di sequenze presenti in file.txt, solo quelle elencate nel file lista.txt. L'estrazione dovrebe rigurdare l'intero header e la riga, ad esso successiva, contenente la sequenza.

Vi ringrazio in anticipo
ixamit
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 499
Iscrizione: giovedì 14 novembre 2013, 10:16

Re: Estrarre righe di testa usando lista

Messaggio da ixamit »

Se è sufficiente in bash puoi provare qualcosa di simile:

Codice: Seleziona tutto

while read line;do grep -A1 "$line" altro_file.txt;done <lista.txt
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4446
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: Estrarre righe di testa usando lista

Messaggio da UbuNuovo »

Se vuoi solo la prima riga dopo il match va bene come ti ha detto Ixami, oppure se vuoi evitare il ciclo puoi provare:

Codice: Seleziona tutto

grep -A1 -f lista.txt file.txt
Però visto quel tipo di file, non è detto che basti solo la prima riga, possono essercene altre.

In questo caso serve la cattura di un blocco di testo su più righe.
Non sapendo se potrò intervenire nuovamente metto più righe di codice con grep, per far vedere come ottenere l'output voluto
Decommenta la riga che ti serve e commenta le altre.
Capito il meccanismo ( '\k' esclude ciò che lo precede e '(?=PATTERN)' esclude da PATTERN in poi), puoi ottenere l'output più o meno completo

Codice: Seleziona tutto

#!/bin/bash

while read line;do 
	grep -Poz ">\K.*(?s)$line.*?(?=>)" file.txt		# ESCLUDO TUTTI I CARATTERI '>'
	#grep -Poz ">.*(?s)$line.*?(?=>)" file.txt		# ESCLUDO I CARATTERI '>' TRA RECORD
	#grep -Poz ">.*(?s)$line.*?>" file.txt			# MANTENGO TUTTI I CARATTERI '>'
done < lista.txt
Considero che ogni record sia terminato da '>'
Se l'ultimo record non avesse il carattere '>' nella riga successiva, lo puoi aggiungere con:

Codice: Seleziona tutto

echo '>' >> file.txt
Salva l'Ucraina! 🇺🇦
genomic
Prode Principiante
Messaggi: 5
Iscrizione: mercoledì 15 marzo 2017, 14:59
Desktop: ubuntu
Distribuzione: Ubuntu 14.04.1 LTS
Sesso: Maschile

Re: Estrarre righe di testa usando lista

Messaggio da genomic »

Grazie a tutti, risolto con la prima soluzione!!! Cmq proverò ad esercitarli anche con le altre che non fa mai male.

PS. Qualcuno potrebbe spiegarmi in dettaglio a cosa corrispondono i vari comandi nella prima soluzione??
ixamit
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 499
Iscrizione: giovedì 14 novembre 2013, 10:16

Re: Estrarre righe di testa usando lista

Messaggio da ixamit »

UbuNuovo ha scritto: Se vuoi solo la prima riga dopo il match va bene come ti ha detto Ixami, oppure se vuoi evitare il ciclo puoi provare:

Codice: Seleziona tutto

grep -A1 -f lista.txt file.txt
Che è sicuramente meglio... la grep provvede a mappare l'intera lista in partenza
genomic ha scritto: PS. Qualcuno potrebbe spiegarmi in dettaglio a cosa corrispondono i vari comandi nella prima soluzione??
esegue una grep per ogni singola riga di lista.txt... ma come detto sopra il comando viene rieseguito N-linee volte

Puoi fare un'ulteriore prova con questo src in C che devi compilare con:

Codice: Seleziona tutto

$ gcc -O2 test.c -o test

Codice: Seleziona tutto

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#define MAX_KEYS  206273
#define ISHEADER(x) *(x)=='>' 
static char key[64];

struct data_s
{
    FILE *fp[2]; 
    unsigned int key[MAX_KEYS];
    size_t num_keys;
};

void fatal(const char *s)
{
    if (errno)
        perror(s);
    else
        fprintf(stderr,"Fatal:%s\n",s);

    exit(EXIT_FAILURE);
}

unsigned int djb2(const char *str)
{
    unsigned int hash = 5381;
    int c;

    while ((c = *str++))
        hash = ((hash << 5) + hash) + c; 

    return hash;
}
unsigned int htable_step(unsigned int k)
{
    return 1 + (k % (MAX_KEYS-1));
}

int load_keys(struct data_s *data)
{
    char *p;
    unsigned int val,rem,step,collisions;

    while(fgets(key,sizeof(key),data->fp[0]))
    {
        if ((p=strchr(key,'\n')))
            *p=0;

        val  = djb2(key);
        rem  = val % MAX_KEYS;
        step = htable_step(val);
        collisions = 0;

        while( collisions < MAX_KEYS && data->key[rem] )
        {
            rem += step;
            rem =  rem % MAX_KEYS;
            collisions++;
        }

        if (collisions == MAX_KEYS)
            fatal("table full");

        data->key[rem] = val;
    }

    return (EXIT_SUCCESS);
}

static inline char *getfield(char *s,char delim, unsigned int n)
{
    char *p;
    int len;

    *key=0;
    while(n--)
    {
        if((p=strchr(s,delim)))
            s=p+1;
        else
            return key;
    }

    if ((len = (p=strchr(s,delim)) ? p-s : strlen(s)-1) > 0)
    {
        strncpy(key,s,len);
        *(key+len)=0;
    }
   
    return key;
}

int search (struct data_s *data)
{
    char *p,line[1024];
    unsigned int val,rem,step,collisions,found=0;

    while(fgets(line,sizeof(line),data->fp[1]))
    {
        if ((p=strchr(line,'\n')))
            *p=0;


        if (ISHEADER(line) && getfield(line,'|',3))
        {

                /* printf("KEY:%s\n",key); */

                val  = djb2(key);
                rem  = val % MAX_KEYS;
                step = htable_step(val);
                collisions = 0;

                while( collisions < MAX_KEYS && data->key[rem] && data->key[rem] != val )
                {
                    rem += step;
                    rem =  rem % MAX_KEYS;
                    collisions++;
                }
                if (data->key[rem]==0 || collisions == MAX_KEYS)
                {
                    /* fprintf(stderr,"*** Warning: key \'%s\' not found\n",key); */
                    found = 0;
                }
                else
                {
                    printf ("%s\n",line);
                    found = 1;
                }
        }
        else if (found)
        {
            printf ("%s\n",line);
        }
    }

    return EXIT_SUCCESS;
}

int main (int argc, char **argv)
{
    static struct data_s data;

    if (argc!=3)
    {
        printf ("Usage: %s <list.txt> <archive.txt>\n",argv[0]);
        printf ("http://forum.ubuntu-it.org/viewtopic.php?f=33&t=619819\n");
        return EXIT_FAILURE;
    }

    if ((data.fp[0]=fopen(argv[1],"r"))==NULL)
        fatal("fopen list");
    if ((data.fp[1]=fopen(argv[2],"r"))==NULL)
        fatal("fopen archive");

    load_keys(&data) , search(&data);

    return EXIT_SUCCESS;
}
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 11 ospiti