[awk] dividir un archivo en varios archivos
ResueltoHola a todos y todas
Estoy dándole vueltas a un script que debe estar 100% en awk, pero me pregunto si finalmente es posible. He intentado con chatGPT pero me saca cualquier cosa :-(
Aquí está mi problema:
- En el siguiente archivo, quiero crear un nuevo archivo cada vez que se encuentre la palabra PAGE en el archivo de entrada. La línea que contiene la palabra PAGE se reporta al inicio del nuevo archivo creado.
- Si en alguna parte del archivo, después de la palabra PAGE, encontramos la palabra NIR, entonces la variable NIR se corrige en consecuencia y se utiliza para nombrar este archivo. El archivo lleva como nombre el valor de la variable NIR, seguido de la extensión ".txt".
Ejemplo :
- Archivo de entrada :
totoo titi PAGE tata tata dfdf fdf NIR un dos tres cuatro tata dfdfd dfdfdf dfdf PAGE dfd fdfdfd dfdf dfddfdfdf NIR uno dos tres cuatro cinco dfdf df PAGE dfdf NIR dfdf dfdfd Resultado esperado :
- El primer archivo creado se llama un.txt y contiene :
titi PAGE tata tata dfdf fdf NIR un dos tres cuatro tata dfdfd El segundo archivo creado se llama uno.txt y contiene :
dfdfdf dfdf PAGE dfd fdfdfd dfdf dfddfdfdf NIR uno dos tres cuatro cinco dfdf - El tercer archivo creado se llama dfdf.txt y contiene :
df PAGE dfdf NIR dfdf dfdfd Gracias de antemano
4 respuestas
-
Colaborador
hola
intentar
$ awk 'BEGIN {while(getline < "archivo")if($0 ~ /NIR/)for(n=1; n<=NF; n++)if($n ~ /NIR/)t[++f]=$(n+1)} /PAGE/ {a=t[++x] ".txt"} a {print $0 > a }' archivo $ $ more *txt :::::::::::::: dfdf.txt :::::::::::::: df PAGE dfdf NIR dfdf dfdfd :::::::::::::: one.txt :::::::::::::: dfdfdf dfdf PAGE dfd fdfdfd dfdf dfddfdfdf NIR uno dos tres cuatro cinco dfdf :::::::::::::: un.txt :::::::::::::: titi PAGE tata tata dfdf fdf NIR un dos tres cuatro tata dfdfd -
Moderador
Hola,
He reescrito el mensaje inicial porque algunas formulaciones eran ambiguas y no me sorprende que ChatGPT se haya tropezado (no creo además que ChatGPT sea capaz de resolver adecuadamente un ejercicio de programación no trivial, pero en fin).
Sea como sea, la definición del problema es incompleta:
- ¿Qué sucede (y debe suceder) si la palabra clave NIR no aparece después de la palabra PAGE?
- ¿Creas aún así un nuevo archivo?
- Si es así, ¿cómo lo nombras?
Buena suerte
- ¿Qué sucede (y debe suceder) si la palabra clave NIR no aparece después de la palabra PAGE?
-
¡Funciona SENSACIONALMENTE BIEN :)
mil gracias!No entiendo cómo funciona el t[++f] en relación al t[++x], si puedes aclarármelo.
-
Moderador
Son solo dos variables diferentes, pero que designan en ambos casos los índices del arreglo t.
- En primer lugar, al iniciar el programa (bloque BEGIN), populas un arreglo t, y cada vez que te encuentras con NIR, registras en el índice actual (notado f) el nombre del futuro archivo.
- Luego, procesas el archivo propiamente dicho, y cada vez que encuentras la palabra PAGE, incrementas un contador (notado arbitrariamente x) que permite recuperar en t el nombre del archivo.
Aprovecho para corregir un pequeño error en la propuesta #1, porque si el archivo no se llama "archivo", no funcionará. En fin, así podría lucir mi_script.awk :
#!/usr/bin/awk -f BEGIN { while (getline < ARGV[1]) { if ($0 ~ /NIR/) { for (n = 1; n <= NF; n++) { if ($n ~ /NIR/) { t[++f] = $(n + 1) } } } } } /PAGE/ { a = t[++x] ".txt" } a { print $0 > a }Algunas observaciones en el camino :
- El primer if (0 ~ /NIR/) es superfluo. En práctica, no aporta nada. De hecho, esta prueba obliga a leer la línea actual, que se volverá a leer una segunda vez en el bucle for que sigue. Esto significa que se leen dos veces las líneas que contienen NIR y una vez las líneas que no contienen NIR. Si eliminamos esta prueba, cada línea se lee solo una vez.
- El bloque /PAGE/ permite definir una variable a, que corresponde al archivo en el que vamos a escribir a partir de ahora. Si esta variable está definida, entonces el tercer bloque se ejecuta cada vez que leemos una nueva línea, y la escribe en el archivo a.
Una vez que el archivo mi_script.awk está escrito, para ejecutarlo :
awk -f mi_script.awk archivo.txt
O también, se otorgan permisos de ejecución al script, y gracias a la primera línea del script, tu shell sabrá que debe usar awk -f :
chmod a+x mi_script.awk ./mi_script.awk archivo.txt
Buena suerte
-
Colaborador
en awk, un arreglo comienza en 1 (no en 0 como en C, por ej.) y una variable indefinida vale 0
en la primera ocurrencia de NIR f=0, entonces t[++f] es igual a t[1], en la siguiente t[2], etc.
volvemos a leer el archivo
en la primera ocurrencia de PAGE x=0, entonces t[++x] es igual a t[1], etc.
volvemos a leer el arreglo t que contiene el nombre del archivo a crear
-
-
gracias a los dos, está muy claro cuando los leo pero muy confuso al sacarlo solo de mi cabeza ;)
Faltas de lógica seguramente