2012-06-25 12 views
5

Parte de mi salida de 4 columnas es el siguiente:encontrar el número y eliminar caracteres adyacentes iguales a este número

5 cc1kcc1kc 5 cc1kcc1kc 
5 cc2ppggg 5 cc2ppggg 
6 ccg12qqqqqqqqqqqqggg 10 ccccg11qqqqqqqqqqqggggg 
3 4qqqqcgc1q 12 cgccgccgccgc 

sólo quiero la segunda y cuarta columnas cambian, ¿hay alguna manera con awk/sed que eliminar los números con los personajes al lado de ellos? ¿O sería más fácil/mejor utilizar una secuencia de comandos de Perl para realizar esta transformación?

La salida resultante debería tener este aspecto:

5 ccccc 5 ccccc 
5 ccggg 5 ccggg 
6 ccgggg 10 ccccgggggg 
3 cgc 12 cgccgccgccgc 

Respuesta

4

Tomando la pregunta literalmente, esto elimina los próximos n caracteres de los campos 2 y 4 para cualquier n incrustado en el campo.

perl -lane 'for $i (1, 3) {@nums = $F[$i] =~ /(\d+)/g; for $num (@nums) {$F[$i] =~ s/$num.{$num}//}}; print join("\t", @F)' 

Las otras respuestas eliminan el número y todos los caracteres que siguen que son iguales.

Para ilustrar la diferencia entre mi respuesta y los demás, utilice la siguiente entrada:

6 ccg8qqqqqqqqqqqqggg 10 ccccg3qqqqqqqqqqqggggg 

mi versión Muestra esto:

6 ccgqqqqggg  10  ccccgqqqqqqqqggggg 

mientras que la producción de ellos esto:

6 ccgggg 10 ccccgggggg 
3

Con perl:

perl -pe 's/\d+([^\d\s])\1*//g' 
+0

+1 porque esto hace el trabajo, pero una pequeña explicación sería agradable. – simbabque

+0

Ok. La opción '-p' hace que Perl asuma el siguiente ciclo alrededor de su código (opción' -e' y one-liner), lo que lo hace iterar sobre argumentos algo así como 'sed'. Y la descripción de expresiones regulares ver en [respuesta sobre 'sed'] (http://stackoverflow.com/a/11186538/1186729). –

+2

Eso elimina el "10" y "12" que se encuentran en la columna 3 en las filas 3 y 4. –

2

Con SED:

sed 's/[0-9]\+\([a-z]\)\1*//g' 

El partido considera que alguna cadena de dígitos ([0-9]+) seguido por cualquier letra ([a-z]). El \1* coincide con cualquier aparición posterior de ese carácter. El modificador /g (global) se asegura de que el reemplazo se realice más de una vez por línea.

1

Esto podría funcionar para usted (GNU sed):

sed 'h;s/\S*\s*\(\S*\).*/\1/;:a;s/[^0-9]*\([0-9]\+\).*/sed "s|\1.\\{\1\\}||" <<<"&"/e;ta;H;g;/\n.*\n/bb;s/\(\S*\s*\)\{3\}\(\S*\).*/\2/;ba;:b;s/^\(\S*\s*\)\(\S*\)\([^\n]*\)\n\(\S*\)/\1\4\3/;s/\(\S*\s*\)\n\(.*\)/\2/' file 
Cuestiones relacionadas