2012-07-19 17 views
10

Vorrei stampare righe dispari (1,3,5,7 ..) senza alcuna modifica, ma anche righe (2,4,6,8) elaborate con la pipeline che inizia con grep. Vorrei scrivere tutto su un nuovo file (linee dispari senza modifiche e nuovi valori per linee pari).Come elaborare ogni altra riga in bash

so come stampare ogni altra linea in awk:

awk ' NR % 2 == 1 { print; } NR % 2 ==0 {print; }' file.fasta 

Tuttavia, anche per le linee, non voglio usare {print; } ma voglio utilizzare il mio pipeline di grep invece.

Un consiglio sarà apprezzato. Molte grazie.

+3

Il '== 1 {print;}' è ridondante, semplicemente 'awk 'NR% 2' stampa linee dispari' – Kevin

+0

grazie a tutti per l'aiuto! – Perlnika

risposta

8

Se hai intenzione di fare un semplice grep, è possibile eliminare la fase addizionale e fare il filtraggio all'interno awk stessa, ad esempio:

awk 'NR % 2 {print} !(NR % 2) && /pattern/ {print}' file.fasta 

Tuttavia, se si intende fare molto più allora, come chepner already pointer out, è possibile infatti tubo dall'interno awk . Per esempio:

awk 'NR % 2 {print} !(NR % 2) {print | "grep pattern | rev" }' file.fasta 

che si apre una pipe al comando "pattern | rev" (notare le virgolette circostanti) e reindirizza l'output di stampa ad esso. Si noti che l'output in questo caso potrebbe non essere come ci si potrebbe aspettare; finirai con l'emissione di tutte le righe dispari prima seguite dall'output del comando pipe (che consuma le linee pari).


(In risposta ai vostri commenti) per contare il numero di caratteri in ogni riga, anche, provare:

awk 'NR % 2 {print} !(NR % 2) {print length($0)}' file.fasta 
+0

Grazie. Sto per contare il numero di lettere in righe pari. – Perlnika

+0

@Perlnika puoi ottenere il numero di caratteri usando il comando 'length' in awk. Vedi risposta aggiornata. –

+0

@Perlnika, alcuni file fasta possono contenere caratteri dispari come '-' o' X', ma probabilmente hai risposto a ciò che l'OP vuole. – Steve

6

È possibile reindirizzare direttamente dall'interno awk:

awk ' NR % 2 == 1 { print; } NR % 2 ==0 {print | "grep -o [actgnACTGN] | wc -l"; }' file.fasta 

Siate consapevoli, tuttavia, che questo non preservare l'ordine del file di input.

(La risposta selezionata è meglio per il compito a portata di mano, ma lascio questa risposta qui come esempio di piping l'istruzione print ad un comando esterno.)

+0

Grazie, ho provato questo con awk 'NR% 2 == 1 {print; } NR% 2 == 0 {stampa | grep -o [actgnACTGN] | wc -l} 'file.fasta (per contare il numero di lettere in linea) ma c'era un problema con wc affermando: awk: riga 1: errore di sintassi in corrispondenza o vicino a wc (in modo che il problema sia nella mia pipeline :) – Perlnika

+0

Cosa intendi per non preservare l'ordine? – Perlnika

+0

@Perlnika Vuol dire che finirai con l'uscita di tutte le linee dispari e poi l'uscita del tubo (che consuma tutte le linee pari) –

1

Al fine di avere la vostra uscita gasdotto appaiono in ordine con la vostra uscita AWK, è necessità di chiudere la pipeline ad ogni iterazione. Questo è, ovviamente, molto inefficiente.

awk 'BEGIN{ cmd = "grep -io \047[actgn]\047 | wc -l" } NR % 2 { print } NR % 2 == 0 { print | cmd; close(cmd) }' file.fasta 

È a quanto pare non si vuole contare i caratteri che non sono nella lista specificata, in modo length($0) non funzionerà. Questo funziona e dovrebbe essere molto più veloce rispetto al metodo gasdotto:

awk 'NR % 2 { print } NR % 2 == 0 {n = split($0, a, /[^actgnACTGN]/); print length($0) - n + 1}' file.fasta 

Funziona suddividendo la linea utilizzando i caratteri non vuole come delimitatori e sottraendo il conteggio delle stringhe dalla lunghezza di la linea e l'aggiunta di 1. In sostanza, sottrae il numero di caratteri indesiderati dalla lunghezza della linea lasciando il numero di caratteri desiderati come risultato.

Problemi correlati