• Publicidad

Crear un bucle dentro de otro

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Crear un bucle dentro de otro

Notapor Merisue » 2007-08-29 23:14 @010

¡Hola a todos de nuevo!

Veréis quería crear un bucle dentro de otro con la función for que es la que controlo por ahora.. :oops: Siguiendo con mi programilla para generar archivos que algunos conoceréis ya (gracias de nuevo explorer) del tema cambiar un archivo, me encuentro con un problema al definir un loop dentro de otro.. Quiero cambiar unas variables de manera que la primera la defino en el primer bucle y quiero que quede fija en un valor mientras con el segundo bucle recorro todo el rango de la segunda variable generando así una serie de archivos tal que siendo la primera variable A y la segunda B queden así A1B1, A1B2, A1B3 y volviendo de nuevo al primer bucle A2B1, A2B2.. y así sucesivamente.. El problema que me encuentro es que me genera solamente archivos tal que A1B3 tantas veces como debería generar los sucesivos archivos. No se si me explico muy bien... así que os dejo aquí mi pequeño programa a ver si me podéis orientar un poco. ¡Gracias por adelantado y un saludo!

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
# Programa genera sucesivos archivos de entrada para FAST.
# ______________________________________________________________________

# Cambiamos la altura de la torre en el archivo_parámetros.
for $i (72..74) {
    for $j (-3..0) {
        # Lugar donde almacenaremos el fichero leido y modificado
        my @params;

        # Abrimos el fichero en lectura
        open (PARAMS, "<PARAMS.in") or die "No se pudo abrir PARAMS.in: $!";

        # Para todas las lineas del fichero hacemos el cambio
        for $line (<PARAMS>) {
            if ($line =~ /^B/) {
                $line  =~ s/=.*\d+/= $j/ or die "No se pudo cambiar el pitch:$!";
            } else {
                ("$line  =~ s/TOWER_HT =.*\d+/TOWER_HT= $i/") == 0 or die "No se cambió la altura de la torre: $!";
            }

            push @params, $line;
        }

        close PARAMS;

        # Grabamos el resultado
        open (OVERWRITE, ">PARAMS.in") or die "No se pudo abrir PARAMS.in: $!";
        print OVERWRITE @params or die "No se pudo sobreescribir PARAMS.in: $!";
        close OVERWRITE;

        # Corre el programa prepro y genera una entrada para FAST.
        system ("c:\\perl\\bin\\perl prepro.pl PARAMS.in FAST.template H$i($j).in") == 0 or die "No se generó el input para FAST: $!";
    }
}
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
Merisue
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2007-08-24 20:13 @884

Publicidad

Notapor explorer » 2007-08-30 05:47 @283

Yo veo que el system es llamado con todas las combinaciones de $i y $j...
Código: Seleccionar todo
H72(-3).in
H72(-2).in
H72(-1).in
H72(0).in
H73(-3).in
H73(-2).in
...
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Merisue » 2007-08-30 08:35 @399

Sí que crea los archivos que tu dices pero no sé por qué cuando entro dentro de todos y cada uno de los archivos creados H es 72 en todos y P es 0 en todos... he ahí el problema.

¡No sé que está mal en el bucle para que no me corra el resto de Hs y corra todos las Ps dejando sólo la última!

Siento no explicarme mejor..
Merisue
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2007-08-24 20:13 @884

Notapor explorer » 2007-08-30 09:19 @430

Ya veo el error... tienes puesta la segunda expresión regular como una cadena de caracteres, entrecomillada. Quita las '"'.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Merisue » 2007-08-30 09:30 @437

He hecho como me has dicho pero ahora no sé qué pasa, no cambia ninguna variable, sólo genera los archivos con los nombres correspondientes pero son todos iguales al original ni siquiera ha cambiado el pitch ni la altura de la torre...
Merisue
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2007-08-24 20:13 @884

Notapor explorer » 2007-08-30 10:06 @463

Lo estoy viendo... el problema son las expresiones regulares... como siempre he dicho, hay que tener mucho cuidado con los glotones (.*)

La siguiente solución sí que me funciona:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
for $i (72..74) {
    for $j (-3..0) {

        # Lugar donde almacenaremos el fichero leido y modificado
        my @params;

        # Abrimos el fichero en lectura
        open (PARAMS, "<PARAMS.in") or die "No se pudo abrir PARAMS.in: $!";

        # Para todas las lineas del fichero hacemos el cambio
        for $line (<PARAMS>) {

              $line =~ s/(\{B.+=.*?)[\d.-]+/$1$j/;
              $line =~ s/(\{TOWER_HT.*=.*?)[\d.-]+/$1$i/;

            push @params, $line;
        }

        close PARAMS;

        # Grabamos el resultado
        open (OVERWRITE, ">PARAMS.in") or die "No se pudo abrir PARAMS.in: $!";
        print OVERWRITE @params or die "No se pudo sobreescribir PARAMS.in: $!";
        close OVERWRITE;

        # Corre el programa prepro y genera una entrada para FAST.
        system ("c:\\perl\\bin\\perl prepro.pl PARAMS.in FAST.template H$i($j).in") == 0 or die "No se genero el input para FAST: $!";

    }
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Los cambios son en las expresión regulares, que, además, las sacamos de los if porque tienen los suficientes controles como para discriminar las líneas.

En cada expresión regular hacemos lo mismo: ponemos un control para verificar que es la línea correcta la que vamos a cambiar. Usamos, de cada línea, las partes que no cambian. En concreto, sabemos que empiezan por '{' y le sigue el nombre del parámetro. Eso lo usaremos como marca de cada sustitución.

En la expresión regular, por ejemplo, /(\{B.+=.*?)[\d.-]+/, lo que hacemos es que la sustitución se hará si coincide con el patrón: la línea comienza por una '{B' , seguida de algo, un '=', seguido de cero o más caracteres que no son dígitos, o '-' o '.'. Todo esto lo capturamos con los paréntesis. Y seguido, de un número.

Aquí, cambiamos de usar un operador glotón (.*) por uno inmediato (.*?). El operador hace lo mismo (captura todo lo posible), PERO queremos que se pare justo antes de lo que le decimos que viene a continuación: un número, no que se trague todos los dígitos y sólo nos devuelva el último.

Si la línea coincide con este patrón, lo sustituimos por $1$j, que quiere decir lo capturado por los paréntesis más el contenido de la variable $j. Digamos que los paréntesis nos capturan toda la línea hasta llegar a la cifra que vamos a sustituir.

La segunda expresión regular es casi igual, solo que buscamos '{TOWER_HT'.

Como ves, hacemos lo siguiente:
* Quitamos los if porque el control de a qué línea debo hacer el cambio lo hace el propio s///;
* En cada s/// ponemos esos controles para identificar cada línea de forma única. Si la línea coincide con lo esperado, hacemos su cambio.
Última edición por explorer el 2007-08-30 19:24 @850, editado 2 veces en total
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Merisue » 2007-08-30 18:05 @795

Pues sigue sin cambiar nada... no sé que más cambiar ya del programa para probarlo... te pongo el archivo PARAMS.in para que veas las líneas a ver si el problema viene de ahí aunque ya me extrañaría con los cambios que me has puesto... perdona por empreñar tanto... :oops: ¡¡y muchísimas gracias por la ayuda!!

Código: Seleccionar todo
{BL_PITCH1 = 5}
{BL_PITCH2 = 5}
{BL_PITCH3 = 5}
{B1_PITCHF1 = 0}
{B1_PITCHF2 = 0}
{B1_PITCHF3 = 0}
{ROT_SPEED = 18.0}
{TIP_RAD = 40.000}
{HUB_RAD = 1.250}
{TOWER_HT =60.000}
{AD_FILE = 1.ipt}
Merisue
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2007-08-24 20:13 @884

Notapor explorer » 2007-08-30 19:22 @848

¡Anda! Pero si ninguna línea empieza por 'B', sino que empieza por '{'.

He modificado mi programa anterior, con unas nuevas expresiones regulares, y una explicación más resumida de lo que hacen. Lo he probado y funciona.

Lo que no dices es si quieres cambiar todos los parámetros que empiezan por 'B' (que son 6) o sólo uno. Tal como está el programa, cambiará todos. Si solo quieres cambiar uno deberás cambiar la expresión regular por una como la del parámetro 'TOWER_HT'.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Merisue » 2007-08-31 04:51 @244

¡Ains, que despiste! Pues es verdad, ¡ahí debe estar el error! Si es que llevo dándole tantas vueltas que cuando se me ocurrió la feliz idea de poner que empezaba por 'B' ya no estaba yo... y no me di cuenta que el otro programa que sí funciona no llevaba que empezase por 'B'...
:oops:

Sí que quiero cambiar todas las líneas que empiezan por 'B'. Probaré a quitar el metacarácter de principio de string y si ya no funciona.. :? ¡¡Muchísimas gracias por todo!!
Merisue
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2007-08-24 20:13 @884

Notapor Merisue » 2007-08-31 06:15 @302

¡Ay, pero que desastrosa soy! ¡Me acabo de dar cuenta de que habías editado el mensaje!! :lol: ¡¡ajaja y funciona con tus modificaciones, va perfecto!! Muchísimas gracias por todo!! :wink:
Merisue
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2007-08-24 20:13 @884


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados