• Publicidad

Expresión regular en una función pasando un string

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

Expresión regular en una función pasando un string

Notapor pablgonz » 2016-07-31 13:19 @597

Hola a todos en el foro.

Tengo escrito un pequeño script para capturar las primeras líneas de un archivo dividiendo éste por medio de una expresión regular para luego analizar la sección que deseo con otras expresiones regulares para pasar las capturas a un array.

El script retorna el resultado esperado de manera correcta. Las líneas que deseo capturar son de la forma
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. % myscript : extraer : { extraer1, extraer2, extraer3} %  (se captura)
  2. %%%%myscript:saltar:{algo, algo2  , algo3  } % (se captura)
  3. % myscript : escapar : { § } % (se captura)
  4. % !myscript : proteger : {archivo.txt, archivo_25.doc} % (no se captura)
  5. % myscript : borrar: {archivo_3.txt, archivo_5.doc}% (se captura)
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

y siempre van en una sola línea.

(Nota: el & #058; anterior corresponde a un carácter ':')

Solo me interesan las palabras entre {...}, sin los espacios ni las comas para pasarlas a un par de array ya definidos, con la excepción de escapar : { § } que es un carácter único y solo deseo quitar los espacios en blanco. Las líneas que contengan !myscript no deseo capturarlas.

Con el siguiente código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.22;
  3. use Text::ParseWords;
  4.  
  5. ### test
  6. my $archivo = '
  7. % myscript : extraer : { extraer1, extraer2, extraer3} %  
  8. %%%%myscript:saltar:{algo, algo2  , algo3  } %
  9. % myscript : escapar : { § }
  10. % !myscript : proteger : {archivo.txt, archivo_25.doc} %%
  11. % myscript : borrar: {archivo_3.txt, archivo_5.doc}
  12. \documentclass{article}%
  13. \begin{document}
  14.  
  15. \begin{verbatim}
  16. \documentclass{article}%
  17. \end{verbatim}
  18.  
  19. \end{document}
  20. lineas ignoradas
  21. ';
  22.  
  23. ### Palabras
  24. my $extraer = 'extraer'; # palabra  
  25. my $saltar  = 'saltar' ; # palabra  
  26. my $escapar = 'escapar'; # carácter único  
  27. my $proteger = 'proteger'; # nombres de archivo .algo
  28. my $borrar  = 'borrar';  # nombres de archivo .algo
  29.  
  30. ### Array
  31. my @extraer_tmp = qw (
  32.   postscript tikzpicture pgfpicture
  33.   );
  34.  
  35. my @saltar_tmp  = qw ();
  36. my @proteger_tmp = qw ();
  37. my @borrar_tmp  = qw ();
  38.  
  39. ### Dividir
  40. my($optin,$documento) = $archivo =~ m/\A (.+?) (\\documentclass.*)\z/msx;
  41.  
  42. ### Reglas  
  43. my $del  = qr/ (?:\s* [:] \s*)/x;  
  44. # my $inicio = qr/^(?:[%]+?\s*? myscript)/x;
  45. my $llaves = qr/ (?:[{])(.+?)(?:[}])  /x;
  46.  
  47. ### extraer en el archivo de entrada
  48. my ($extraer_in) = $optin =~ m/^(?:[%]+?\s*? myscript) $del $extraer $del $llaves/msx;
  49. my @extraer_in = $extraer_in;
  50. s/^\s*|\s*//mg foreach @extraer_in;  
  51. my @extraer_ok = quotewords('\,', 0,@extraer_in);
  52. push(@extraer_tmp,@extraer_ok);
  53.  
  54. say "Esto contiene extraer_tmp : @extraer_tmp";
  55.  
  56. ### saltar en el archivo de entrada
  57. my ($saltar_in) = $optin =~ m/^(?:[%]+?\s*? myscript) $del $saltar $del $llaves/msx;
  58. my @saltar_in = $saltar_in;
  59. s/^\s*|\s*//mg foreach @saltar_in; # quitar espacios en blanco
  60. my @saltar_ok = quotewords('\,', 0,@saltar_in);
  61. push(@saltar_tmp,@saltar_ok);
  62.  
  63. say "Esto contiene saltar_tmp: @saltar_tmp";
  64.  
  65. ### escapar en el archivo de entrada
  66. my ($escapar_in) = $optin =~ m/^(?:[%]+?\s*? myscript) $del $escapar $del $llaves/msx;
  67. my @escapar_in = $escapar_in;
  68. s/^\s*|\s*//mg foreach @escapar_in; # quitar espacios en blanco
  69. my $escapar = join '', @escapar_in;
  70.  
  71. say "Esto contiene escapar: $escapar";
  72.  
  73. ### proteger en el archivo de entrada
  74. my ($proteger_in) = $optin =~ m/^(?:[%]+?\s*? myscript) $del $proteger $del $llaves/msx;
  75. my @proteger_in = $proteger_in;
  76. s/^\s*|\s*//mg foreach @proteger_in; # quitar espacios en blanco
  77. my @proteger_ok = quotewords('\,', 0,@proteger_in);
  78. push(@proteger_tmp,@proteger_ok);
  79.  
  80. say "Esto contiene proteger_tmp: @proteger_tmp";
  81.  
  82. ### borrar en el archivo de entrada
  83. my ($borrar_in) = $optin =~ m/^(?:[%]+?\s*? myscript) $del $borrar $del $llaves/msx;
  84. my @borrar_in = $borrar_in;
  85. s/^\s*|\s*//mg foreach @borrar_in; # quitar espacios en blanco
  86. my @borrar_ok = quotewords('\,', 0,@borrar_in);
  87. push(@borrar_tmp,@borrar_ok);
  88.  
  89. say "Esto contiene borrar_tmp: @borrar_tmp";
  90.  
  91. __END__
  92.  
Coloreado en 0.006 segundos, usando GeSHi 1.0.8.4

Obtengo lo que deseo, pero repito varias veces el mismo código para las palabras que irán en un array y en el futuro extenderé los casos que deseo capturar. ¿Puedo escribir esto como una función? ¿o escribir el código de manera más compacta?

Saludos.
pablgonz
Perlero nuevo
Perlero nuevo
 
Mensajes: 236
Registrado: 2010-09-08 21:03 @919
Ubicación: Concepción (Chile)

Publicidad

Re: Expresión regular en una función pasando un string

Notapor explorer » 2016-07-31 17:34 @774

Este es un ejemplo de cómo obtener la información, en una estructura de hash de arrays:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.22;
  3. use utf8;
  4. use open qw(:std :utf8);
  5.  
  6.  
  7. ### test
  8. my $archivo = '
  9. % myscript : extraer : { extraer1, extraer2, extraer3} %
  10. %%%%myscript:saltar:{algo, algo2    , algo3    } %
  11. % myscript : escapar : { § }
  12. % !myscript : proteger : {archivo.txt, archivo_25.doc} %%
  13. % myscript : borrar: {archivo_3.txt, archivo_5.doc}
  14. \documentclass{article}%
  15. \begin{document}
  16.  
  17. \begin{verbatim}
  18. \documentclass{article}%
  19. \end{verbatim}
  20.  
  21. \end{document}
  22. lineas ignoradas
  23. ';
  24.  
  25. #
  26. # gramática
  27. my $rx_myscrypt = qr/
  28.     ^ %+ \s* myscript (?&SEPARADOR) (?<clave>(?&CLAVE)) (?&SEPARADOR) \{ (?<argumentos>(?&ARGUMENTOS)) \}
  29.     (?(DEFINE)
  30.         (?<CLAVE>      \w+       )
  31.         (?<ARGUMENTOS> .+?       )
  32.         (?<SEPARADOR>  \s* : \s* )
  33.     )
  34. /mx;
  35.  
  36. #
  37. # Dividir
  38. my($optin, $documento) = $archivo =~ m/\A \s* (.+?) \s* (\\documentclass .+) $/msx;
  39.  
  40. #
  41. # Procesar
  42. my %resultado;
  43.  
  44. while ($optin =~ /$rx_myscrypt/g) {
  45.     my($clave, $argumentos) = @+{qw(clave argumentos)};
  46. #    say "[$clave => [$argumentos]";
  47.  
  48.     my @argumentos = split /\s*,\s*?/, $argumentos;
  49.     for (@argumentos) {
  50.         s/^ \s* | \s* $//gx;
  51.     }
  52. #    say "\t[", join("," => @argumentos), "]";
  53.  
  54.     push @{ $resultado{ $clave } }, @argumentos;
  55. }
  56.  
  57. #
  58. # Salida
  59. use Data::Dumper;
  60. say Dumper \%resultado;
  61.  
  62. __END__
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
La salida es algo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$VAR1 = {
          'extraer' => [
                       'extraer1',
                       'extraer2',
                       'extraer3'
                     ],
          'borrar' => [
                      'archivo_3.txt',
                      'archivo_5.doc'
                    ],
          'escapar' => [
                       "\x{a7}"
                     ],
          'saltar' => [
                      'algo',
                      'algo2',
                      'algo3'
                    ]
        };
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Entonces, se ve claro: las claves del hash son los nombres que aparecen después de 'myscrypt', y los valores son referencias a arrays que almacenan los argumentos.

Si queremos restringir lo que son las claves que nos interesan, podemos modificar la regla CLAVE, por algo como esto

(?<CLAVE> extraer | borrar | escapar | saltar )

pero eso luego nos obliga a tener que reeditarlo cuando cambien las condiciones.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Expresión regular en una función pasando un string

Notapor pablgonz » 2016-08-01 22:07 @963

Gracias por la respuesta, explorer; se ajusta perfecto a lo que deseo y por fin veo en acción a ?(DEFINE)

Si estoy en lo correcto solo me faltaría añadir:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. # este array ya esta definido en el script
  2. my @extraer_tmp  = qw (
  3.     postscript tikzpicture pgfpicture
  4.     );
  5. # si la clave existe, la añado al array
  6. if(exists($resultado{extraer})){
  7. my @extraer_ok = values %resultado{extraer};
  8. push(@extraer_tmp,@extraer_ok);
  9. }
  10. say Dumper @extraer_tmp;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
es decir, reviso si la clave existe, y si es así, añado el valor capturado al array si éste ya está definido en el script o creo un nuevo con los valores en caso de que no exista, ¿es la manera correcta?

Una consulta (para variar), añadiste use utf8 y use open qw(:std :utf8), ¿quiere decir que el archivo de entrada debe estar codificado en utf8 por obligación? ¿podré leer archivos en codificaciones distintas, latin1 por ejemplo? Lo más probable es que mis archivos de entrada estén en utf8, pero, no siempre es así (sobre todo con los archivo más antiguos).

Saludos.
pablgonz
Perlero nuevo
Perlero nuevo
 
Mensajes: 236
Registrado: 2010-09-08 21:03 @919
Ubicación: Concepción (Chile)

Re: Expresión regular en una función pasando un string

Notapor explorer » 2016-08-02 05:42 @279

pablgonz escribiste:es decir, reviso si la clave existe, y si es así, añado el valor capturado al array si éste ya está definido en el script o creo un nuevo con los valores en caso de que no exista, ¿es la manera correcta?
No, el valor de $resultado{extraer} es una referencia a un array, no un hash.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. if (exists $resultado{extraer} ) {
  2.     push @extraer_tmp, @{ $resultado{extraer} };
  3. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Pero no sé por qué mantener dos arrays separados (no sé para qué les vas a necesitar por separado). Si el problema general de 'extraer' es el de tratar un único array, se podría hacer el push() directamente a $resultado{extraer} (no probado):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. push @{ $resultado{extraer} }, (qw(postscript tikzpicture pgfpicture))
  2.     if exists $resultado{extraer};
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


pablgonz escribiste:Una consulta (para variar), añadiste use utf8 y use open qw(:std :utf8), ¿quiere decir que el archivo de entrada debe estar codificado en utf8 por obligación? ¿podré leer archivos en codificaciones distintas, latin1 por ejemplo? Lo más probable es que mis archivos de entrada estén en utf8, pero, no siempre es así (sobre todo con los archivo más antiguos).
Los puse porque en el código había un carácter '§', y como a) iba a sacarlo en pantalla, y b) mi programa lo estaba editando con codificación utf-8, le tenía que indicar a Perl que "eso de ahí" no eran un par de bytes cualesquiera, sino un carácter bien definido.

Si no decimos nada, Perl sacará lo que nosotros le hayamos puesto, sin preguntar. Si la ristra de bytes tiene significado para la terminal o el archivo donde estemos escribiendo, Perl no lo sabe -ni tiene por qué saberlo-.

Ahora bien... si estamos leyendo información en una codificación y queremos guardarla en otra, sí que tenemos que tener cuidado de decirle a Perl qué es lo que está gestionando.

En tu caso, si no dices nada (no pones use utf8 ni el open), Perl tratará todo lo que llegue como ristra de octetos codificados en latin1 (bytes, a efectos prácticos), así que eso es justo lo que mandará fuera. Por eso te ha funcionado bien, porque Perl trata la E/S como bytes de la misma codificación.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Expresión regular en una función pasando un string

Notapor pablgonz » 2016-08-02 21:20 @931

Muchas gracias por la aclaraciones, siempre me confundo los distintos contextos en los que se usa % y los distintos pragmas.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. if (exists $resultado{extraer} ) {
  2.     push @extraer_tmp, @{ $resultado{extraer} };
  3. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Las líneas que propones son justo lo que deseo, tengo varios array ya definidos dentro del script usando Getopt::Long para recibir argumentos desde la línea de comandos.

Como algunas veces las líneas están en el archivo de entrada y otras veces no, las añado a las que ya tengo definidas; luego, con un poco de operatoria de conjuntos sobre los array, elimino los duplicados y me aseguro que las palabras que están en 'extraer' no se encuentren en 'saltar', por ejemplo.

Revisaré un poco más sobre las referencias y el uso de %hash, por lo que he leído en la red es uno de los puntos fuertes de Perl.

Saludos,
Pablo
pablgonz
Perlero nuevo
Perlero nuevo
 
Mensajes: 236
Registrado: 2010-09-08 21:03 @919
Ubicación: Concepción (Chile)

Re: Expresión regular en una función pasando un string

Notapor explorer » 2016-08-03 03:34 @190

Aprender a operar con los hash es algo básico, con Perl. Por ejemplo, también te ahorraría operaciones de "evitar duplicados", ya que las claves de un hash son únicas.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Expresión regular en una función pasando un string

Notapor pablgonz » 2016-08-12 16:35 @733

¿Se puede modificar la estructura del %hash en el script para acceder a los valores de una línea de la forma
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  1. % myscript : opciones : {picdir = images, verb = coment, prefix = tabla, xetex, clear}
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

usando algo como
Sintáxis: [ Descargar ] [ Ocultar ]
  1. $resultado{opciones}{picdir} 
  2. $resultado{opciones}{verb} 
  3. $resultado{opciones}{prefix} 
? Es decir, al igual que las otras líneas que capturo, me interesan las palabras separadas por comas sin espacios, pero, si está picdir = algo1, verb = algo2, prefix = algo3 solo me quiero quedar con las palabras a la derecha del signo '=' (algo1, algo 2, algo3), siempre van en la línea % myscript : opciones : y son solo esas tres palabras: 'picdir', 'verb', 'prefix', las cuales a veces están y otras veces no.

¿Se puede hacer esto usando la misma idea del %hash o se debe crear un nuevo array con values %resultado{opciones} y usar split /=/?

Saludos.
pablgonz
Perlero nuevo
Perlero nuevo
 
Mensajes: 236
Registrado: 2010-09-08 21:03 @919
Ubicación: Concepción (Chile)

Re: Expresión regular en una función pasando un string

Notapor explorer » 2016-08-12 20:06 @879

La modificación es muy sencilla, creando un apartado para esa excepción.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.22;
  3. #use utf8;
  4. #use open qw(:std :utf8);
  5.  
  6.  
  7. ### test
  8. my $archivo = '
  9. % myscript : extraer : { extraer1, extraer2, extraer3} %
  10. %%%%myscript&#058;saltar:{algo, algo2    , algo3    } %
  11. % myscript : escapar : { § }
  12. % !myscript : proteger : {archivo.txt, archivo_25.doc} %%
  13. % myscript : borrar: {archivo_3.txt, archivo_5.doc}
  14. % myscript : opciones : {picdir = images, verb = coment, prefix = tabla, xetex, clear}
  15. \documentclass{article}%
  16. \begin{document}
  17.  
  18. \begin{verbatim}
  19. \documentclass{article}%
  20. \end{verbatim}
  21.  
  22. \end{document}
  23. lineas ignoradas
  24. ';
  25.  
  26. #
  27. # gramática
  28. my $rx_myscrypt = qr/
  29.     ^ %+ \s* myscript (?&SEPARADOR) (?<clave>(?&CLAVE)) (?&SEPARADOR) \{ (?<argumentos>(?&ARGUMENTOS)) \}
  30.     (?(DEFINE)
  31.         (?<CLAVE>      \w+       )
  32.         (?<ARGUMENTOS> .+?       )
  33.         (?<SEPARADOR>  \s* : \s* )
  34.     )
  35. /mx;
  36.  
  37. #
  38. # Dividir
  39. my($optin, $documento) = $archivo =~ m/\A \s* (.+?) \s* \\documentclass /msx;
  40.  
  41. #
  42. # Procesar
  43. my %resultado;
  44.  
  45. while ($optin =~ /$rx_myscrypt/g) {
  46.     my($clave, $argumentos) = @+{qw(clave argumentos)};
  47. #    say "[$clave => [$argumentos]";
  48.  
  49.     my @argumentos = split /\s*,\s*?/, $argumentos;
  50.     for (@argumentos) {
  51.         s/^ \s* | \s* $//gx;
  52.     }
  53. #    say "\t[", join("," => @argumentos), "]";
  54.  
  55.     if ($clave eq 'opciones') {
  56.         for my $argumento (@argumentos) {
  57.             if ($argumento =~ /(?<key>\S+) \s* = \s* (?<valor>\S+)/x) {
  58.                 $resultado{$clave}{$+{'key'}} = $+{'valor'};
  59.             }
  60.         }
  61.     }
  62.     else {
  63.         push @{ $resultado{ $clave } }, @argumentos;
  64.     }
  65. }
  66.  
  67. #
  68. # Salida
  69. use Data::Dumper;
  70. say Dumper \%resultado;
  71.  
  72. __END__
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
La salida ahora es:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$VAR1 = {
          'extraer' => [
                         'extraer1',
                         'extraer2',
                         'extraer3'
                       ],
          'opciones' => {
                          'prefix' => 'tabla',
                          'picdir' => 'images',
                          'verb' => 'coment'
                        },
          'borrar' => [
                        'archivo_3.txt',
                        'archivo_5.doc'
                      ],
          'saltar' => [
                        'algo',
                        'algo2',
                        'algo3'
                      ],
          'escapar' => [
                         '§'
                       ]
        };
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Como ves, ahora %resultado contiene una entrada más, 'opciones', pero el valor que contiene no es una referencia a un array sino a un hash.

Eso sí... el que vaya a leer el contenido de %resultado debe acordarse de que la entrada 'opciones' debe leerse de forma distinta que el resto de claves.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Expresión regular en una función pasando un string

Notapor pablgonz » 2016-08-13 15:17 @678

Genial, es justo lo que buscaba. ¡Un %hash dentro de una referencia! No pensé que se podía hacer eso.

Una cosa más, ¿cómo accedo al resto de los valores de esa misma línea? Quiero ver si están o no presentes y no tienen la forma palabra = algo, son solo palabras, como xetex. Por ejemplo, intenté con:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. # % myscript : opciones : {picdir = images, verb = coment, prefix = tabla, xetex, clear}
  2. # sacamos el valor de picdir
  3. say $resultado{opciones}{picdir}; # muestra images, Ok
  4.  
  5. # tratamos de ver si xetex esta en la línea opciones
  6. if(exists $resultado{opciones}{xetex}){
  7.         say "xetex encontrado";
  8. }
  9. else {
  10.         say "xetex no encontrado";
  11. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
pero, no funciona.

Agradecido,
Pablo
pablgonz
Perlero nuevo
Perlero nuevo
 
Mensajes: 236
Registrado: 2010-09-08 21:03 @919
Ubicación: Concepción (Chile)

Re: Expresión regular en una función pasando un string

Notapor explorer » 2016-08-14 14:10 @632

pablgonz escribiste:Genial, es justo lo que buscaba. ¡Un %hash dentro de una referencia! No pensé que se podía hacer eso.
No, no es así.

Un hash almacena pares de valores en la forma clave/valor. Y eso dos valores son solo escalares. Pero una referencia es un valor escalar. De esa manera, podemos guardar una referencia como valor dentro de una pareja clave/valor. Y una referencia es un "puntero" a otro tipo de dato (escalar, array, hash).

Más información en tu propio ordenador en perldoc perlref, y en la Web (traducido al español).

pablgonz escribiste:Una cosa más, ¿cómo accedo al resto de los valores de esa misma línea? Quiero ver si están o no presentes y no tienen la forma palabra = algo, son solo palabras, como xetex.
Pero es que creí entender que solo querías los valores que tuviesen un '=', no los demás.

A la hora de guardar esos elementos, surge una duda: ¿cómo lo hacemos para que sea de forma más o menos igual que el resto de datos? Esto es importante para que luego no tengamos que usar un código de lectura complicado.

Como lo estamos haciendo en forma de un hash, se me ocurren dos opciones. La primera es que cuando encontremos uno de estos argumentos, lo guardemos como clave y un valor ficticio de '1'. El resultado sería así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
          'opciones' => {
                          'prefix' => 'tabla',
                          'picdir' => 'images',
                          'clear' => 1,
                          'xetex' => 1,
                          'verb' => 'coment'
                        },
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
Y vemos que los argumentos aparecen como unas claves más.

Otra opción es guardar todos esos argumentos en una única clave especial, en forma de array:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
          'opciones' => {
                          'picdir' => 'images',
                          'otros' => [
                                       'xetex',
                                       'clear'
                                     ],
                          'prefix' => 'tabla',
                          'verb' => 'coment'
                        }
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
Ahí nos inventamos la clave 'otros' que almacena una referencia a un array con todos los argumentos solitarios encontrados.

La siguiente versión del programa contiene las dos opciones (son las líneas 61 y 62). Tú eliges cuál de las dos prefieres.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.22;
  3. #use utf8;
  4. #use open qw(:std :utf8);
  5.  
  6.  
  7. ### test
  8. my $archivo = '
  9. % myscript : extraer : { extraer1, extraer2, extraer3} %
  10. %%%%myscript&#058;saltar:{algo, algo2    , algo3    } %
  11. % myscript : escapar : { § }
  12. % !myscript : proteger : {archivo.txt, archivo_25.doc} %%
  13. % myscript : borrar: {archivo_3.txt, archivo_5.doc}
  14. % myscript : opciones : {picdir = images, verb = coment, prefix = tabla, xetex, clear}
  15. \documentclass{article}%
  16. \begin{document}
  17.  
  18. \begin{verbatim}
  19. \documentclass{article}%
  20. \end{verbatim}
  21.  
  22. \end{document}
  23. lineas ignoradas
  24. ';
  25.  
  26. #
  27. # gramática
  28. my $rx_myscrypt = qr/
  29.     ^ %+ \s* myscript (?&SEPARADOR) (?<clave>(?&CLAVE)) (?&SEPARADOR) \{ (?<argumentos>(?&ARGUMENTOS)) \}
  30.     (?(DEFINE)
  31.         (?<CLAVE>      \w+       )
  32.         (?<ARGUMENTOS> .+?       )
  33.         (?<SEPARADOR>  \s* : \s* )
  34.     )
  35. /mx;
  36.  
  37. #
  38. # Dividir
  39. my($optin, $documento) = $archivo =~ m/\A \s* (.+?) \s* \\documentclass /msx;
  40.  
  41. #
  42. # Procesar
  43. my %resultado;
  44.  
  45. while ($optin =~ /$rx_myscrypt/g) {
  46.     my($clave, $argumentos) = @+{qw(clave argumentos)};
  47. #    say "[$clave => [$argumentos]";
  48.  
  49.     my @argumentos = split /\s*,\s*?/, $argumentos;
  50.     for (@argumentos) {
  51.         s/^ \s* | \s* $//gx;
  52.     }
  53. #    say "\t[", join("," => @argumentos), "]";
  54.  
  55.     if ($clave eq 'opciones') {
  56.         for my $argumento (@argumentos) {
  57.             if ($argumento =~ /(?<key>\S+) \s* = \s* (?<valor>\S+)/x) {
  58.                 $resultado{$clave}{$+{'key'}} = $+{'valor'};
  59.             }
  60.             else {
  61.                 $resultado{$clave}{$argumento} = 1;                     # método 1
  62.                 push @{$resultado{$clave}{'otros'}}, $argumento;        # método 2
  63.             }
  64.         }
  65.     }
  66.     else {
  67.         push @{ $resultado{ $clave } }, @argumentos;
  68.     }
  69. }
  70.  
  71. #
  72. # Salida
  73. use Data::Dumper;
  74. say Dumper \%resultado;
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Siguiente

Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron