Relacionado, pero sin respuestas satisfactorias: ¿Cómo puedo dividir un archivo de texto grande en partes de 500 palabras más o menos?
Estoy tratando de tomar un archivo de texto ( http://mattmahoney.net/dc/text8.zip ) con> 10 ^ 7 palabras en una sola línea, y dividirlo en líneas con N palabras cada una. Mi enfoque actual funciona, pero es bastante lento y feo (usando el script de shell):
i=0
for word in $(sed -e 's/\s\+/\n/g' input.txt)
do
echo -n "${word} " > output.txt
let "i=i+1"
if [ "$i" -eq "1000" ]
then
echo > output.txt
let "i=0"
fi
done
¿Algún consejo sobre cómo puedo hacer esto más rápido o más compacto?
text-processing
sed
awk
split
Cory Schillaci
fuente
fuente
Respuestas:
Suponiendo que su definición de palabra es una secuencia de caracteres no en blanco separados por espacios en blanco, aquí hay una
awk
solución para su archivo de una sola líneafuente
Uso
xargs
(17 segundos):Utiliza la
-n
bandera de laxargs
cual define el número máximo de argumentos. Sólo cambia1000
a500
o lo que sea que desee limitar.Hice un archivo de prueba con 10 ^ 7 palabras:
Aquí están las estadísticas de tiempo:
fuente
xargs
's comportamiento cotización-strippingn
más lento será, para que lo sepas. Con-n10
lo cancelé después de unos 8 minutos de espera ...Perl parece sorprendentemente bueno en esto:
Cree un archivo con 10,000,000 palabras separadas por espacios
Ahora, perl para agregar una nueva línea después de cada 1,000 palabras
Sincronización
verificar resultados
La solución awk aceptada tardó poco más de 5 segundos en mi archivo de entrada.
fuente
No es realmente adecuado cuando el número
N
de palabras es un número grande, pero si es un número pequeño (e idealmente, no hay espacios iniciales / finales en su archivo de una línea), esto debería ser bastante rápido (por ejemplo, 5 palabras por línea):fuente
paste
cadena sobre la marcha. Por ejemplo:tr -s '[[:blank:]]' '\n' < text8 | paste -d' ' $(perl -le 'print "- " x 1000')
set
etc., e incluso entonces, hay un número máximo de argumentos específicos del sistema (no estoy familiarizado con todos los sabores depaste
pero Creo que con algunas implementaciones hay límites en cuanto al número de args / archivos de entrada y / o la longitud de la línea de salida ...)El mismo comando sed puede simplificarse especificando cuántos patrones de espacio de palabras desea hacer coincidir. No tenía ningún archivo de cadena grande para probarlo, pero sin los bucles en su script original, esto debería ejecutarse tan rápido como su procesador pueda transmitir los datos. Beneficio adicional, funcionará igualmente bien en archivos de varias líneas.
fuente
El venerable
fmt(1)
comando, aunque no opera estrictamente con "un número particular de palabras", puede envolver líneas largas con bastante rapidez a un objetivo en particular (o máximo) de ancho:O con perl moderno, para un número específico de palabras, digamos, 10, y asumiendo un solo espacio como límite de la palabra:
fuente
Los coreutils
pr
comando es otro candidato: la única arruga parece ser que es necesario forzar el ancho de la página para que sea lo suficientemente grande como para acomodar el ancho de salida.Usando un archivo creado usando el generador de 10,000,000 palabras de @ Glenn_Jackman,
donde los recuentos se confirman de la siguiente manera
[La solución perl de Glenn es aún un poco más rápida, ~ 1.8s en esta máquina].
fuente
en Go lo intentaría así
fuente