¿Eliminar filas duplicadas en vi?


123

Tengo un archivo de texto que contiene una larga lista de entradas (una en cada línea). Algunos de estos son duplicados y me gustaría saber si es posible (y si es así, cómo) eliminar los duplicados. Estoy interesado en hacer esto desde vi / vim, si es posible.



4
Este tiene 1 año; ese es 10 meses. Entonces, al revés.
Sydius

El consenso de @Sydius ahora es priorizar el recuento de votos a favor (del que también tienes más): meta.stackexchange.com/questions/147643/… Y esos no son duplicados, ese no menciona a Vim :-)
Ciro Santilli 郝海东 冠状 病六四 事件 法轮功

Respuestas:



25

Prueba esto:

:%s/^\(.*\)\(\n\1\)\+$/\1/

Busca cualquier línea seguida inmediatamente por una o más copias de sí mismo y la reemplaza con una sola copia.

Sin embargo, haga una copia de su archivo antes de intentarlo. No está probado.


1
@hop Gracias por probarlo por mí. No tenía acceso a vim en ese momento.
Sean

2
esto resalta todas las líneas duplicadas para mí pero no se borran, ¿me estoy perdiendo un paso aquí?
ak85

Estoy bastante seguro de que esto también resaltará una línea seguida de una línea que tiene el mismo "prefijo" pero es más larga.
hippietrail

3
El único problema con esto es que si tiene múltiples duplicados (3 o más de las mismas líneas), debe ejecutar esto muchas veces hasta que desaparezcan todos los dups, ya que esto solo los elimina un conjunto de dups a la vez.
horta

2
Otro inconveniente de esto: esto no funcionará a menos que sus líneas duplicadas ya estén una al lado de la otra. Clasificar primero sería una forma de asegurarse de que estén uno al lado del otro. En ese momento, las otras respuestas probablemente sean mejores.
horta

23

Desde la línea de comando simplemente haz lo siguiente:

sort file | uniq > file.new

1
Esto fue muy útil para mí para un archivo enorme. ¡Gracias!
Rafid

1
No pude conseguir que la respuesta aceptada funcionara, ya que :sort uestaba colgando en mi archivo grande. Esto funcionó muy rápida y perfectamente. ¡Gracias!
Tgsmith61591

1
'uniq' is not recognized as an internal or external command, operable program or batch file.
hippietrail

1
Sí, probé esta técnica en un archivo de 2,3 GB y fue sorprendentemente rápido.
DanM

@hippietrail ¿Estás en una PC con Windows? Quizás puedas usar cygwin.
12431234123412341234123

8

awk '!x[$0]++' yourfile.txtsi desea conservar el orden (es decir, la clasificación no es aceptable). Para invocarlo desde vim, :!se puede utilizar.


4
¡Esto es adorable! ¡No necesitar ordenar es exactamente lo que estaba buscando!
Cometsong

6
g/^\(.*\)$\n\1/d

Funciona para mí en Windows. Sin embargo, las líneas deben ordenarse primero.


1
Esto eliminará una línea que sigue a una línea que es su prefijo: aaaaseguida de aaaabbeliminará por aaaaerror.
hippietrail

5

Combinaría dos de las respuestas anteriores:

go to head of file
sort the whole file
remove duplicate entries with uniq

1G
!Gsort
1G
!Guniq

Si estaba interesado en ver cuántas líneas duplicadas se eliminaron, use control-G antes y después para verificar la cantidad de líneas presentes en su búfer.


1
'uniq' is not recognized as an internal or external command, operable program or batch file.
hippietrail

3

Seleccione las líneas en modo de línea visual ( Shift+ v), luego :!uniq. Eso solo detectará duplicados que vengan uno tras otro.


1
Solo tenga en cuenta que esto solo funcionará en computadoras con el programa uniq instalado, es decir, Linux, Mac, Freebsd, etc.
anteatersa

Esta será la mejor respuesta para aquellos que no necesitan clasificación. Y si es usuario de Windows, considere probar Cygwin o MSYS.
fx-kirin

1

Con respecto a cómo se puede implementar Uniq en VimL, ​​busque Uniq en un complemento que estoy manteniendo . Verá varias formas de implementarlo que se proporcionaron en la lista de correo de Vim.

De lo contrario, :sort ues de hecho el camino a seguir.


0
:%s/^\(.*\)\(\n\1\)\+$/\1/gec

o

:%s/^\(.*\)\(\n\1\)\+$/\1/ge

Esta es mi respuesta para ti, ¡puede eliminar varias líneas duplicadas y solo mantener una, no eliminar!


0

yo usaría !}uniq , pero eso solo funciona si no hay líneas en blanco.

Para cada línea en un archivo de uso: :1,$!uniq.


0

Esta versión solo elimina las líneas repetidas que están contigo. Quiero decir, solo borra líneas repetidas consecutivas. Usando el mapa dado, la función nota problemas con líneas en blanco. Pero si cambia el REGEX para que coincida con el inicio de la línea ^, también eliminará las líneas en blanco duplicadas.

" function to delete duplicate lines
function! DelDuplicatedLines()
    while getline(".") == getline(line(".") - 1)
        exec 'norm! ddk'
    endwhile
    while getline(".") == getline(line(".") + 1)
        exec 'norm! dd'
    endwhile
endfunction
nnoremap <Leader>d :g/./call DelDuplicatedLines()<CR>

0

Un método alternativo que no usa vi / vim (para archivos muy grandes) es, desde la línea de comandos de Linux, use sort y uniq:

sort {file-name} | uniq -u

0

Esto funcionó para mí para ambos .csvy.txt

awk '!seen[$0]++' <filename> > <newFileName>

Explicación: La primera parte del comando imprime filas únicas y la segunda parte, es decir, después de la flecha central, es para guardar la salida de la primera parte.

awk '!seen[$0]++' <filename>

>

<newFileName>

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.