[root@server]# awk '!seen[$0]++' out.txt > cleaned
awk: (FILENAME=out.txt FNR=8547098) fatal error: internal error
Aborted
[root@server]#
El "" servidor "" tiene: 8 GByte RAM + 16 GByte SWAP, x> 300 GByte de espacio libre, amd64, CPU de escritorio. Linux científico 6.6. No se ejecuta nada más para hacer CARGA. Awk aborta después de unos segundos. Out.txt es ~ 1.6 GByte. GNU Awk 3.1.7.
Pregunta : ¿Cómo puedo eliminar las líneas duplicadas manteniendo el orden de las líneas? El caso también es importante, por ejemplo: "A" y "a" son dos líneas diferentes, hay que mantenerlo. Pero "a" y "a" están duplicados, solo se necesita el primero.
La respuesta podría estar en cualquier cosa ... si awk no es bueno para esto ... entonces perl / sed ... ¿cuál podría ser el problema?
[root@server]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 61945
max locked memory (kbytes, -l) 99999999
max memory size (kbytes, -m) unlimited
open files (-n) 999999
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 99999999
cpu time (seconds, -t) unlimited
max user processes (-u) 61945
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[root@server]#
Actualización: Probé esto en una máquina RHEL, no aborta, pero no tuve tiempo de esperar a que termine ... ¿por qué SL Linux no difiere de RHEL?
Actualización: Estoy probando una conjetura virtual de Ubuntu 14 ... ¡hasta ahora funciona! No es un problema ulimit : mawk 1.3.3
root@asdf-VirtualBox:~# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 51331
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 51331
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
root@asdf-VirtualBox:~#
fuente
awk
versiones en dos máquinas?out.txt
? ¿Funciona el mismo comando si lo prueba en un archivo más pequeño? ¿Cuántos usuarios hay en la máquina? ¿Había suficiente memoria disponible para el proceso? ¿Hay algo especial en la línea 8547098 del archivo de entrada?Respuestas:
Dudo que haga una diferencia, pero, por si acaso, aquí está cómo hacer lo mismo en Perl:
Si el problema es mantener las líneas únicas en la memoria, tendrá el mismo problema
awk
que intentó. Entonces, otro enfoque podría ser:Cómo funciona:
En un sistema GNU,
cat -n
antepondrá el número de línea a cada línea siguiendo una cantidad de espacios y seguido de un carácter <tab> .cat
canaliza esta representación de entrada asort
.sort
La-k2
opción le indica que solo considere los caracteres desde el segundo campo hasta el final de la línea al ordenar, ysort
divide los campos de forma predeterminada en espacios en blanco (ocat
espacios insertados y <tab> ) .Cuando lo sigue
-k1n
,sort
primero considera el segundo campo y luego, en el caso de-k2
campos idénticos , considera el primer campo pero ordenado numéricamente. Por lo tanto, las líneas repetidas se ordenarán juntas pero en el orden en que aparecieron.uniq
—que se le dice que ignore el primer campo (-f1
- y también como separados por espacios en blanco) — y que da como resultado una lista de líneas únicas en el archivo original y se canaliza de nuevo asort
.sort
ordena numéricamente en el primer campo (cat
número de línea insertado) , volviendo el orden de clasificación al que estaba en el archivo original y canalizando estos resultadoscut
.cut
elimina los números de línea que fueron insertados porcat
. Esto se efectúacut
imprimiendo solo desde el segundo campo hasta el final de la línea (ycut
el delimitador predeterminado es un carácter <tab> ) .Para ilustrar:
fuente
sort
! Pero la mayoríasort
puede hacerlouniq
por sí mismo para que pueda acortar su guiónsort -uk2 | sort -bk1,1n
sort
? Pensé que-u
era una característica de GNU.-u
y especificar que debería ignorar el primer campo? Segúnman sort
,-u
esta no es una de las opciones posibles-f
, por lo que no creo que se pueda usar aquí.EDITAR 1: ¿Realmente funciona? (comparando)
Caso1 : 100_000_000 números aleatorios (5 dígitos cada uno), 566Mbytes, 31_212 valores diferentes:
Caso 2 : 50_000_000 números de rand (10 dígitos cada uno), 516Mbytes, 48_351_464 valores diferentes:
(los siguientes números no son muy precisos):
sol2 con caché es:
Ordenar también se puede optimizar agregando una opción de tamaño de caché (no hecho).
Una conclusión rápida:
sort
Es un comando fantástico!fuente
sort -uk2
ysort -nk1,1
son diferentes El primero considera desde la clave 2cd hasta el final de la línea, el segundo considera solo la primera clave. Debería cambiar su lugarsort -nk1
allí; incluso podría ser más rápido de esa manera, pero definitivamente será más confiable. Por cierto, esas son algunas cajas bonitas.cat -n
¿una pestaña ? No sé cómo funciona ese comando.cat -n
transfrom felizmente cada unoline
enspaces + the number + \t + line
- el formato ideal para ordenar y cortarhe usado
BINMODE = rw: para mantener felices los terminadores de fin de línea. (Vivo en un entorno mixto)
La lógica es simple.
Si la línea actual no está en la matriz asociativa, agréguela a la matriz asociativa e imprima en la salida.
Puede haber limitaciones de memoria con este enfoque. Para archivos y conjuntos de archivos muy grandes, he usado variaciones sobre esto, usando el almacenamiento de archivos para superar las limitaciones.
fuente
La semántica de preservación del orden de su problema tiene una propiedad maravillosa: puede subdividir el problema. Puedes hacerlo
split -l 1000000
en el archivo de entrada; las piezas de 1000000 líneas que produce tienen nombres ordenados léxicamente, lo cual es bueno; luego unifique las piezas; y luego (como una segunda pasada) uniqify las salidas de esos.Esto resuelve el problema de falta de memoria (limitando el requisito de memoria) a expensas de convertirlo en una solución multipass.
Específicamente:
Generar datos de entrada:
Dividir los datos de entrada:
Ejecute el uniqifier de una vez (conserva todas las líneas de entrada únicas en la memoria):
Ejecute el unificador en piezas divididas (retiene solo líneas de entrada únicas de cada pieza en la memoria), luego reduzca como una segunda pasada:
Comparar:
No sé la proporción de líneas únicas a no únicas en su entrada, ni qué tan bien mezcladas están las líneas de entrada, por lo que hay algunos ajustes que hacer en términos de la cantidad de archivos divididos que necesita.
fuente
Otro enfoque (que vale la pena publicar como respuesta separada) es: en lugar del enfoque de archivo dividido que crea archivos temporales, realice el procesamiento por lotes dentro del propio software uniqifier. Por ejemplo, usando una implementación de uniqifier Ruby con fines explicativos:
La idea es limpiar el hash-set de vez en cuando. Entonces esto se vuelve iterativo:
Por lo tanto, puede ejecutar esta versión limitada repetidamente, hasta que el recuento de líneas no cambie de una iteración a la siguiente.
Tenga en cuenta que esta técnica capi-uniqm es independiente del lenguaje: puede borrar la
lines_seen
matriz cada N líneas si está utilizando awk, python, perl, C ++, etc. Existen métodos de limpieza clara para todos estos idiomas; Creo queawk
'sdelete
no es estándar, pero común.fuente