Tengo dos archivos de texto: string.txt y lengths.txt
String.txt:
abcdefghijklmnopqrstuvwxyz
lengths.txt
5
4
10
7
Quiero obtener el archivo
>Entry_1
abcde
>Entry_2
fghi
>Entry_3
jklmnopqrs
>Entry_4
tuvwxyz
Estoy trabajando con unas 28,000 entradas y varían entre 200 y 56,000 caracteres.
Por el momento, estoy usando:
start=1
end=0
i=0
while read read_l
do
let i=i+1
let end=end+read_l
echo -e ">Entry_$i" >>outfile.txt
echo "$(cut -c$start-$end String.txt)" >>outfile.txt
let start=start+read_l
echo $i
done <lengths.txt
Pero es muy ineficiente. ¿Alguna idea mejor?
linux
shell-script
usuario3891532
fuente
fuente

str="$(cat string.txt)"; i=0; while read j; do echo "${file:$i:$j}"; i=$((i+j)); done <length.txtparece lo suficientemente rápido como lo hace solo por shell ..{ while read l<&3; do head -c"$l"; echo; done 3<lengths.txt; } <String.txt.Respuestas:
Tu puedes hacer
Requiere alguna explicación:
La idea principal es usar
{ head ; } <filey se deriva de la respuesta subestimada @mikeserv . Sin embargo, en este caso, necesitamos usar muchosheads, por lo quewhilese introduce un bucle y se ajusta un poco con los descriptores de archivo para pasar a laheadentrada de ambos archivos (archivoString.txtcomo archivo principal para procesar y líneas desdelength.txtcomo argumento a-copción) . La idea es que el beneficio de la velocidad debe provenir de no tener que buscar a través de laString.txtcada vez que un comando comoheadocutse invoca. Elechoes solo para imprimir nueva línea después de cada iteración.Cuánto más rápido (si lo hay) y agregar
>Entry_ientre líneas se deja como ejercicio.fuente
read -u 3para leer el descriptor 3.bash. La gran mayoría de los sistemas basados en Linux no tienebashinstalado (piense en Android y otros sistemas integrados).bashSiendo el caparazón más lento de todos, el cambio a bash probablemente degradará el rendimiento de manera más significativa que la poca ganancia que podría generar el cambio deread <&3aread -u3(que en cualquier caso será insignificante en comparación con el costo de ejecutar un comando externo comohead). Cambiar a ksh93 que tieneheadincorporado (y uno que admite la-copción no estándar ) mejoraría mucho más el rendimiento.head -c(para lasheadimplementaciones donde está disponible esa opción no estándar) es un número de bytes, no caracteres. Eso marcaría la diferencia en configuraciones regionales de varios bytes.En general, no desea utilizar bucles de shell para procesar texto . Aquí, usaría
perl:Ese es un comando, que lee (con almacenamiento en búfer de manera mucho más eficiente que el
readcomando del shell que lee un byte (o unos pocos bytes para archivos normales) a la vez) ambos archivos solo una vez (sin almacenarlos llenos en la memoria), así es serán varios órdenes de magnitud más eficientes que las soluciones que ejecutan comandos externos en un bucle de shell.(agregue la
-Copción si esos números deben ser números de caracteres en la configuración regional actual en lugar de número de bytes. Para caracteres ASCII como en su muestra, eso no hará ninguna diferencia).fuente
$_como parámetro de salida y entradaread, pero reduce el recuento de bytes en el script.bash, 16 segundos conPATH=/opt/ast/bin:$PATH ksh93)).bash, versión 4
salida
fuente
¿Qué hay de
awk?Cree un archivo llamado
process.awkcon este código:Guárdalo y ejecuta
awk -f process.awk lengths.txt string.txtfuente
PROCINFO, esto no es estándarawk, perogawk. En ese caso, preferiría otragawkcaracterística única, laFIELDWIDTHS:awk -vFIELDWIDTHS="$(tr '\n' ' ' < lengths.txt)" '{for(i=1;i<=NF;i++)print">Entry"i ORS$i}' string.txt