2012-04-19 16 views
8

Estoy buscando una versión más específica del comando :sort u, que eliminará todas las líneas duplicadas de un archivo. Estoy trabajando con un csv, y quiero eliminar todas las líneas donde la entrada de la segunda columna tiene un duplicado. Un ejemplo debería ayudar a aclarar:: ordena u - pero solo en una columna en un csv?

a,1,b 
g,1,f 
c,1,x 
i,2,l 
m,1,k 
o,2,p 
u,1,z 

comando sort debe ceder:

a,1,b 
i,2,l 

nota: las filas específicas que se mantienen no son importantes, siempre y cuando después de la ordenación de las entradas de la columna 2 ª son todos únicos

¿Qué comando vim producirá el resultado anterior?

Gracias!

+1

¿Por qué debe hacerse esto en 'vim'? Tengo que pensar que usar un analizador de CSV real para hacer el trabajo sería más fácil. (A menos que esté seguro de que su entrada _ nunca_ tendrá ',' incrustado en valores con comillas o estilo de barra invertida ...) – sarnold

+2

No * tiene * que hacerse en vim; Te estoy preguntando cómo lo harías vim. Puedo pensar en muchas otras formas de hacerlo ... pero estoy buscando una solución vim. – Jonah

Respuesta

10

Dado que no es posible lograr la transformación bajo la pregunta en una ejecución del comando :sort, considerámoslo como un proceso de dos pasos.

El primer paso es ordenar las líneas por los valores de la segunda columna de separada por comas. Para hacer eso, podemos usar el comando :sort pasando una expresión regular que coincida con la primera columna y la siguiente coma de separación. Como :sort compara el texto que comienza justo después de la coincidencia del patrón especificado en cada línea, nos da el orden de clasificación deseado.

:sort/^[^,]*,/ 

para comparar los valores numéricamente, no lexicográfico, utilice el n bandera:

:sort n/^[^,]*,/ 

El segundo paso implica la ejecución a través de las líneas de selección ya la eliminación de todos ellos excepto uno, entre los que tienen la misma valor en la segunda columna. Es conveniente para construir nuestra implementación en el comando :global que ejecuta el comando Ex dado en las líneas que coinciden con cierto patrón. Por definición, una línea se puede eliminar si contiene el mismo valor en la segunda columna como en la siguiente línea. Esta formalización (acompañado con la suposición inicial que comas no pueden ocurrir en los valores de columna) nos da el siguiente patrón:

^[^,]*,\([^,]*\),.*\n[^,]*,\1,.* 

lo tanto, si se corre el comando :delete en cada línea que satisface este patrón, de arriba hacia abajo, tendremos solo una línea para cada valor distinto en la segunda columna .

:g/^[^,]*,\([^,]*\),.*\n[^,]*,\1,.*/d_ 

Tanto de los pasos se pueden combinar en un comando Ex,

:sort/^[^,]*,/|g/^[^,]*,\([^,]*\),.*\n[^,]*,\1,.*/d_ 
+0

whoa, eso sí funciona. ¿Podrías analizar lo que está pasando? – Jonah

+1

excelente explicación. tyvm. – Jonah

1
:sort /\([^,]*,\)\{1}/ 
:g/\%(\%([^,]*,\)\{1}\1.*\n\)\@<=\%([^,]*,\)\{1}\([^,]*\)/d 

primero ordenar por columna con índice 1. segundo partido cualquier línea whos índice de la columna 1 partidos las siguientes líneas columna índice 1 y eliminarlo.

índice de columna es el 1 en el {1}. se repite 3 veces

+0

oh, es más o menos lo mismo que la respuesta de ib. no se dio cuenta en ese momento. mantenimiento debido a la diferencia de parámetro de índice de columna –

+0

Correcto. La idea es más o menos la misma, excepto que tu patrón mira hacia atrás, mientras que el mío mira hacia adelante (es más simple). –

+0

Tom, gracias por su respuesta también – Jonah

0

usando segunda columna

(visual + !sort) 

usando tercera columna

sort -k 3 

o

:sort /.*\%3v/ 

O

select the lines you wish to sort using the Capital V command. Then enter 
!sort -k 3n 

o saltar las primeras dos palabras en cada línea y ordenar con lo que sigue:

:%sort /^\S\+\s\+\S\+\s\+/ 

o

ordenar por columna lastest

:%sort /\<\S\+\>$/ r 

O utilizar otro programa, como MS Office, u OPENOFFICE

Cuestiones relacionadas