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.txt
parece 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 ; } <file
y se deriva de la respuesta subestimada @mikeserv . Sin embargo, en este caso, necesitamos usar muchoshead
s, por lo quewhile
se introduce un bucle y se ajusta un poco con los descriptores de archivo para pasar a lahead
entrada de ambos archivos (archivoString.txt
como archivo principal para procesar y líneas desdelength.txt
como argumento a-c
opción) . La idea es que el beneficio de la velocidad debe provenir de no tener que buscar a través de laString.txt
cada vez que un comando comohead
ocut
se invoca. Elecho
es solo para imprimir nueva línea después de cada iteración.Cuánto más rápido (si lo hay) y agregar
>Entry_i
entre líneas se deja como ejercicio.fuente
read -u 3
para leer el descriptor 3.bash
. La gran mayoría de los sistemas basados en Linux no tienebash
instalado (piense en Android y otros sistemas integrados).bash
Siendo 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 <&3
aread -u3
(que en cualquier caso será insignificante en comparación con el costo de ejecutar un comando externo comohead
). Cambiar a ksh93 que tienehead
incorporado (y uno que admite la-c
opción no estándar ) mejoraría mucho más el rendimiento.head -c
(para lashead
implementaciones 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
read
comando 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
-C
opció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.awk
con este código:Guárdalo y ejecuta
awk -f process.awk lengths.txt string.txt
fuente
PROCINFO
, esto no es estándarawk
, perogawk
. En ese caso, preferiría otragawk
característica única, laFIELDWIDTHS
:awk -vFIELDWIDTHS="$(tr '\n' ' ' < lengths.txt)" '{for(i=1;i<=NF;i++)print">Entry"i ORS$i}' string.txt