2012-07-19 17 views
10

Me gustaría imprimir líneas impares (1,3,5,7 ..) sin ningún cambio, pero incluso las líneas (2,4,6,8) procesan con una tubería que comienza con grep. Me gustaría escribir todo en un archivo nuevo (líneas impares sin ningún cambio y nuevos valores para líneas pares).Cómo procesar cada otra línea en bash

sé cómo imprimir cada dos líneas en awk:

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

Sin embargo, incluso para las líneas, no quiero usar {print; } pero quiero usar mi tubería grep lugar.

Un consejo será apreciado. Muchas gracias.

+3

El '== 1 {print;}' es redundante, simplemente 'awk 'NR% 2' imprimirá líneas impares' – Kevin

+0

¡gracias a todos por la ayuda! – Perlnika

Respuesta

8

Si usted está planeando hacer una sencilla grep, puede acabar con el paso adicional y hacer el filtrado dentro de awk sí mismo, por ejemplo:

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

Sin embargo, si la intención de hacer mucho más entonces, como chepner already pointer out, puede de hecho tubería desde el interior de awk . Por ejemplo:

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

que se abre una tubería al comando "pattern | rev" (nótese las comillas circundantes) y redirige la salida de impresión a la misma. Tenga en cuenta que el resultado en este caso puede no ser el esperado; terminará con todas las líneas impares siendo salidas primero seguidas por la salida del comando canalizado (que consume las líneas pares).


(En respuesta a sus comentarios) para contar el número de caracteres en cada línea, incluso, intenta:

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

Gracias. Estoy a punto de contar el número de letras en líneas pares. – Perlnika

+0

@Perlnika puede obtener el número de caracteres utilizando el comando 'length' en awk. Ver respuesta actualizada. –

+0

@Perlnika, algunos archivos fasta pueden contener caracteres extraños como '-' o' X', pero probablemente haya respondido lo que desea el OP. – Steve

6

Puede canalizar directamente desde el interior awk:

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

Tenga en cuenta, sin embargo, que esto no va a preservar el orden de su archivo de entrada.

(La respuesta seleccionada es mejor para la tarea en cuestión, pero voy a dejar esta respuesta aquí como un ejemplo de una tubería de la sentencia de impresión a un comando externo.)

+0

Gracias, lo he intentado con awk 'NR% 2 == 1 {print; } NR% 2 == 0 {imprimir | grep -o [actgnACTGN] | wc -l} 'archivo.fasta (para contar el número de letras en línea) pero había un problema con wc que decía: awk: línea 1: error de sintaxis en o cerca de wc (de modo que supongo que el problema está en mi tubería :) – Perlnika

+0

¿Qué quieres decir con no preservando el orden? – Perlnika

+0

@Perlnika Quiere decir que terminará con todas las líneas impares saliendo primero, seguido de la salida de la tubería (que consume todas las líneas pares) –

1

Con el fin de tener su salida de la tubería aparecen en orden con la salida de AWK, se necesidad de cerrar la tubería en cada iteración. Esto es, por supuesto, muy ineficiente.

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

Evidentemente, usted no desea contar con personajes que no están en la lista especificada, por lo length($0) no va a funcionar. Esto funciona y debe ser mucho más rápido que el método de la tubería:

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

Funciona mediante el fraccionamiento de la línea utilizando los caracteres que no quiere como delimitadores y restando el recuento de las subcadenas de la longitud de la línea y agregando 1. En esencia, resta el número de caracteres no deseados de la longitud de la línea y deja como resultado el número de caracteres deseados.

Cuestiones relacionadas