Estrarre righe di testa usando lista
-
- 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
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
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
Re: Estrarre righe di testa usando lista
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
- UbuNuovo
- 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
Se vuoi solo la prima riga dopo il match va bene come ti ha detto Ixami, oppure se vuoi evitare il ciclo puoi provare:
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
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
grep -A1 -f lista.txt file.txt
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
Se l'ultimo record non avesse il carattere '>' nella riga successiva, lo puoi aggiungere con:
Codice: Seleziona tutto
echo '>' >> file.txt
Salva l'Ucraina!
-
- 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
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??
PS. Qualcuno potrebbe spiegarmi in dettaglio a cosa corrispondono i vari comandi nella prima soluzione??
Re: Estrarre righe di testa usando lista
Che è sicuramente meglio... la grep provvede a mappare l'intera lista in partenzaUbuNuovo 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
esegue una grep per ogni singola riga di lista.txt... ma come detto sopra il comando viene rieseguito N-linee voltegenomic ha scritto: PS. Qualcuno potrebbe spiegarmi in dettaglio a cosa corrispondono i vari comandi nella prima soluzione??
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;
}
Chi c’è in linea
Visualizzano questa sezione: 0 utenti iscritti e 11 ospiti