Estoy tratando de comparar para comparar dos formas diferentes de procesar un archivo. Tengo una pequeña cantidad de datos de entrada, pero para obtener buenas comparaciones, necesito repetir las pruebas varias veces.
En lugar de repetir las pruebas, me gustaría duplicar los datos de entrada varias veces (por ejemplo, 1000) para que un archivo de 3 líneas se convierta en 3000 líneas y pueda ejecutar una prueba mucho más satisfactoria.
Estoy pasando los datos de entrada a través de un nombre de archivo:
mycommand input-data.txt
perl
es tan eficiente que está diseñado para esto.Originalmente estaba pensando que tendría que generar un archivo secundario, pero podría simplemente repetir el archivo original en Bash y usar alguna redirección para que aparezca como un archivo.
Probablemente hay una docena de formas diferentes de hacer el ciclo, pero aquí hay cuatro:
El tercer método allí se improvisa a partir del comentario de maru a continuación y crea una gran lista de nombres de archivos de entrada para cat.
xargs
dividirá esto en tantos argumentos como lo permita el sistema. Es mucho más rápido que n gatos separados.La
awk
forma (inspirada en la respuesta de terdon ) es probablemente la más optimizada, pero duplica cada línea a la vez. Esto puede o no adaptarse a una aplicación en particular, pero es increíblemente rápido y eficiente.Pero esto se está generando sobre la marcha. Es probable que la salida de Bash sea mucho más lenta de lo que algo puede leer, por lo que debe generar un nuevo archivo para probar. Afortunadamente, esa es solo una extensión muy simple:
fuente
cat $(for i in {1..N}; do echo filename; done)
. Esto tiene la limitación del tamaño de arg, pero debería ser más rápido.Aquí hay una
awk
solución:Es esencialmente tan rápido como Perl de @Gnuc (corrí 1000 veces y obtuve el tiempo promedio):
fuente
awk '{for(i=0; i<1000; i++)print}' input-data.txt
que solo emita 1000 copias de cada línea a la vez. No se adapta a todas las ocasiones, pero incluso más rápido, menos demora y no necesita mantener todo el archivo en la RAM.123123123
estaba bien, pero111222333
no lo estaba. Su versión es claramente más rápida que la de Gnouc, tiene un promedio de 0.00297 segundos. EDITAR: tacha eso, cometí un error, en realidad es equivalente a 0.004013 segundos.Solo usaría un editor de texto.
Si absolutamente necesita hacerlo a través de la línea de comandos (esto requiere que tenga
vim
instalado, yavi
que no tiene el:normal
comando), puede usar:Aquí,
-es
(o-e -s
) hace que vim funcione silenciosamente, por lo que no debería tomar el control de la ventana de su terminal, y-u NONE
evita que vea su vimrc, lo que debería hacer que funcione un poco más rápido de lo que lo haría de otra manera (tal vez mucho más rápido, si usa muchos complementos vim).fuente
Aquí hay una línea simple, sin secuencias de comandos involucradas:
Explicación
`yes input-data.txt | head -1000 | paste -s`
produce el textoinput-data.txt
1000 veces separado por espacios en blancocat
una lista de archivos.fuente
xargs paste -s
? Esto funciona, pero no conserva las nuevas líneas en el archivo de entrada.Mientras trabajaba en un script completamente diferente, aprendí que con 29 millones de líneas de texto, el uso
seek()
y la operación de byte de datos a menudo es más rápido que línea por línea. La misma idea se aplica en la secuencia de comandos a continuación: abrimos el archivo y, en lugar de recorrerlo abriendo y cerrando el archivo (lo que puede agregar una sobrecarga, incluso si no es significativo), mantenemos el archivo abierto y volvemos al principio.El script en sí es bastante simple en uso:
Para un archivo de texto de 3 líneas y 1000 iteraciones, todo va bastante bien, aproximadamente 0.1 segundos:
El script en sí no es muy elegante, probablemente podría acortarse, pero hace el trabajo. Por supuesto, agregué algunos bits adicionales aquí y allá, como la
error_out()
función, que no es necesaria, es solo un pequeño toque fácil de usar.fuente
Podemos resolver esto sin un archivo adicional, ni programas especiales, puro Bash (bueno, cat es un comando estándar).
Basado en una característica de printf dentro de bash podemos generar una cadena repetida):
Luego, podemos enviar dicha lista de 1000 nombres de archivo (repetidos) y llamar a cat:
Y finalmente, podemos dar el resultado al comando para ejecutar:
O, si el comando necesita recibir la entrada en el stdin:
Sí, se necesita el doble <.
fuente
Generaría un nuevo archivo usando Unix para loop:
fuente