• Publicidad

Acotar expresión regular

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

Re: Acotar expresión regular

Notapor pablgonz » 2014-02-04 13:14 @593

En pantalla no me arroja nada, pero, en el fichero que genera no se llevan a cabo los cambios, elimina las frases que debería convertir... por eso tengo dudas con given/when... ya que al modificar por if/else, conservando el resto del código, funciona.
pablgonz
Perlero nuevo
Perlero nuevo
 
Mensajes: 236
Registrado: 2010-09-08 21:03 @919
Ubicación: Concepción (Chile)

Publicidad

Re: Acotar expresión regular

Notapor explorer » 2014-02-04 13:28 @602

Entonces es necesario poner esto al principio del código:

use experimental 'smartmatch';
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

Re: Acotar expresión regular

Notapor pablgonz » 2014-02-04 18:29 @811

Instalé el módulo y agregué la línea que me indicas y no funcionó. Estoy utilizando Perl v5.18.2 (Strawberry portable 32 bits). Sigue siendo un absoluto misterio (para mi) el por qué no funciona, creo que el problema podría estar en el substr, que es donde se deberían hacer los cambios o es algo en el funcionamiento interno de SmartMatch o es alguno de los casos de excepción comentados en http://search.cpan.org/~rjbs/perl-5.18.2/pod/perlsyn.pod#Experimental_Details_on_given_and_when.
Saludos,
Pablo

P.D.: La verdad es que este misterio me tiene bastante ocupado, modificando a if/else resolví el problema, pero, es interesante (e intrigante) saber por qué dejo de funcionar el script.
pablgonz
Perlero nuevo
Perlero nuevo
 
Mensajes: 236
Registrado: 2010-09-08 21:03 @919
Ubicación: Concepción (Chile)

Re: Acotar expresión regular

Notapor explorer » 2014-02-04 20:52 @911

Yo necesitaría ver el código original junto con un archivo de prueba, y el archivo resultado. Si puedes meterlos en un zip y adjuntarlos en el siguiente mensaje, podemos ver qué pasa.
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

Re: Acotar expresión regular

Notapor pablgonz » 2014-02-04 21:11 @924

Ok, te adjunto un fichero comprimido con los archivos y el script.

P.D.: El script y los archivos son de otro tema que quedo unido a este hilo (en la hoja 2).

Gracias nuevamente.
Adjuntos
foro2014.zip
test-out-ok.tex es el archivo esperado
(3.39 KiB) 82 veces
pablgonz
Perlero nuevo
Perlero nuevo
 
Mensajes: 236
Registrado: 2010-09-08 21:03 @919
Ubicación: Concepción (Chile)

Re: Acotar expresión regular

Notapor explorer » 2014-02-05 17:14 @760

Ya lo encontré. Es algo muy extraño, pero no que no funcione en Perl v5.18.2, sino que sí funcione en versiones anteriores :)

Este es el nuevo código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.18.2;
  3. no warnings;
  4. use autodie;
  5.  
  6. @ARGV == 1 or die "Uso: $0 <archivo LaTeX a procesar\n";
  7.  
  8. my $nombre_archivo_entrada = shift;
  9.  
  10. -f $nombre_archivo_entrada or die "ERROR: No encuentro $nombre_archivo_entrada\n";
  11.  
  12.  
  13. ## Lectura del archivo
  14. open my $ENTRADA, '<', $nombre_archivo_entrada;
  15. undef $/;                                                                       # modo 'slurp'
  16. my $archivo_entrada = <$ENTRADA>;
  17. close   $ENTRADA;
  18.  
  19.  
  20. ## Partición del documento
  21. my($cabeza,$cuerpo,$final) = $archivo_entrada =~ m/\A (.+? ^\\begin{document}) \s* (.+?) \s* (^ \\end{document}) \s* \z/msx;
  22.  
  23.  
  24. ## Cambios a realizar
  25. my %cambios = (
  26.         '\pspicture'            => '\TRICKS',
  27.         '\endpspicture'         => '\ENDTRICKS',
  28.  
  29.         '\begin{pspicture'      => '\begin{TRICKS',
  30.         '\end{pspicture'        => '\end{TRICKS',
  31.  
  32.         '\postscript'           => '\POSTRICKS',
  33.  
  34.         '\begin{postscript}'    => '\begin{POSTRICKS}',
  35.         '\end{postscript}'      => '\end{POSTRICKS}',
  36. );
  37.  
  38.  
  39. ## Variables y constantes
  40. my $no_del = "\0";
  41. my $del    = $no_del;
  42.  
  43. ## Reglas
  44. my $llaves      = qr/\{ .+? \}                                                                  /x;
  45. my $no_corchete = qr/(?:\[ .+? \])?                                                             /x;
  46. my $delimitador = qr/\{ (?<del>.+?) \}                                                          /x;
  47. my $verb        = qr/verb [*]?                                                                  /ix;
  48. my $lst         = qr/lstinline (?!\*) $no_corchete                                              /ix;
  49. my $mint        = qr/mint      (?!\*) $no_corchete $llaves                                      /ix;
  50. my $marca       = qr/\\ (?:$verb | $lst | $mint) (\S) .+? \g{-1}                                /x;
  51. my $comentario  = qr/^ \s* \%+ .+? $                                                            /mx;
  52. my $definedel   = qr/\\ (?:   DefineShortVerb | lstMakeShortInline  ) $no_corchete $delimitador /ix;
  53. my $indefinedel = qr/\\ (?: UndefineShortVerb | lstDeleteShortInline) $llaves                   /ix;
  54.  
  55.  
  56. ## Cambiar
  57. while ($cuerpo =~
  58.     /   $marca
  59.     |   $comentario
  60.     |   $definedel
  61.     |   $indefinedel
  62.     |   $del .+? $del
  63.     /pgmx) {
  64.  
  65.     my($pos_inicial, $pos_final) = ($-[0], $+[0]);                              # posiciones
  66.     my $encontrado = ${^MATCH};                                                 # lo encontrado
  67.  
  68.     given ($encontrado) {
  69.         when (/$definedel/) {                                                   # definimos delimitador
  70.             $del = $+{del};
  71.             $del = "\Q$+{del}" if substr($del,0,1) ne '\\';                     # es necesario "escapar" el delimitador
  72.         }
  73.         when (/$indefinedel/) {                                                 # indefinimos delimitador
  74.             $del = $no_del;
  75.         }
  76.         default {                                                               # Aquí se hacen los cambios
  77.             while (my($busco, $cambio) = each %cambios) {
  78.                 $encontrado =~ s/\Q$busco\E/$cambio/g;                          # es necesario escapar $busco, ya que contiene caracteres extraños
  79.             }
  80.  
  81.             substr $cuerpo, $pos_inicial, $pos_final-$pos_inicial, $encontrado; # insertamos los nuevos cambios
  82.  
  83.             pos($cuerpo) = $pos_inicial + length $encontrado;                   # reposicionamos la siguiente búsqueda
  84.         }
  85.     }
  86. }
  87.  
  88.  
  89. ## Escritura del resultado
  90. open my $SALIDA, '>', "test-out2.tex";
  91. print   $SALIDA "$cabeza\n$cuerpo\n$final\n";
  92. close   $SALIDA;
  93.  
  94. __END__
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4
Los cambios son mínimos, pero claro, hay que saber cuáles hay que poner :)
  • en la línea 2 ponemos un 'use' para indicar que este código funciona con la última versión estable de Perl (si la tenemos instalada, claro)
  • en la línea 3 desactivamos los 'warnings', y así dejamos de ver los avisos de 'característica experimental' del given/when
  • como estamos usando un Perl >= v5.14, ya no hace falta la línea 'use strict;', así que la quitamos
  • y... la línea problemática... es la 63. Ahí faltaba por poner la opción '/p'. Sin ella, no se actualiza la variable '${^MATCH}' de la línea 66
Y esto es lo curioso: con una versión anterior de Perl, sí que funciona el programa sin la opción '/p' (preservar). Pero la documentación en perlvar dice que sí hay que ponerlo.

Otra opción sería quitar la opción '/p' y cambiar entonces '${^MATCH}' por '$&', pero la velocidad del programa disminuye.

Misterio resuelto: hay que programar según cómo lo diga la documentación :D
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

Re: Acotar expresión regular

Notapor pablgonz » 2014-02-05 18:42 @821

Genial, había ocupado "/p" en el resto de las expresiones y me percaté de que funcionaba a medias... nunca intenté en la línea que usaste, es más, no sabía si usarlo o no, no lo veo muy seguro en expresiones regulares... en fin... misterio resuelto y mis disculpas a given/when.
Saludos.
pablgonz
Perlero nuevo
Perlero nuevo
 
Mensajes: 236
Registrado: 2010-09-08 21:03 @919
Ubicación: Concepción (Chile)

Re: Acotar expresión regular

Notapor pablgonz » 2014-03-16 14:24 @641

Hice unos pequeños cambios en el script y lo dejé así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use autodie;                                            # muere si ocurre un error
  4. use File::Basename;                                     # separa el archivo de entrada
  5.  
  6. ### Argumentos --------------------------------------------------------------
  7. @ARGV == 1  or die "Uso: $0 <archivo TeX a procesar>\n";
  8. my $nombre_archivo = shift;
  9. -f $nombre_archivo or die "ERROR: No encuentro [$nombre_archivo]\n";
  10.  
  11. ### Arreglo de la extensión -------------------------------------------------
  12. my @SuffixList = ('.tex', '', '.ltx');                  # posible extensión
  13. my ($name, $path, $ext) = fileparse($nombre_archivo, @SuffixList);
  14. $ext = '.tex' if not $ext;                              # fijamos la extensión
  15.  
  16. ### Abrimos el archivo de entrada a modificar -------------------------------
  17. open my $ENTRADA, '<', $nombre_archivo;
  18. my $archivo;
  19. {
  20.     local $/;
  21.     $archivo = <$ENTRADA>;
  22. }
  23. close   $ENTRADA;
  24.  
  25. ## Partición del documento
  26. my($cabeza,$cuerpo,$final) = $archivo =~ m/\A (.+? ^\\begin{document}) (.+) (^ \\end{document} .*) \z/msx;
  27.  
  28. ## Cambios a realizar
  29. my %cambios = (
  30.         '\pspicture'                => '\TRICKS',
  31.         '\endpspicture'             => '\ENDTRICKS',
  32.  
  33.         '\begin{MYexample'          => '\begin{MYEXAMPLE',
  34.         '\end{MYexample'            => '\end{MYEXAMPLE',
  35.        
  36.         '\begin{pspicture'          => '\begin{TRICKS',
  37.         '\end{pspicture'            => '\end{TRICKS',
  38.        
  39.         '\begin{postscript}'        => '\begin{POSTRICKS}',
  40.         '\end{postscript}'          => '\end{POSTRICKS}',
  41. );
  42.  
  43.  
  44. ## Variables y constantes
  45. my $no_del = "\0";
  46. my $del    = $no_del;
  47.  
  48. ## Reglas
  49. my $llaves      = qr/\{ .+? \}                                                                  /x;
  50. my $no_corchete = qr/(?:\[ .+? \])?                                                             /x;
  51. my $delimitador = qr/\{ (?<del>.+?) \}                                                          /x;
  52. my $verb        = qr/verb [*]?                                                                  /ix;
  53. my $lst         = qr/lstinline (?!\*) $no_corchete                                              /ix;
  54. my $mint        = qr/mint      (?!\*) $no_corchete $llaves                                      /ix;
  55. my $marca       = qr/\\ (?:$verb | $lst | $mint) (\S) .+? \g{-1}                                /x;
  56. my $comentario  = qr/^ \s* \%+ .+? $                                                            /mx;
  57. my $definedel   = qr/\\ (?:   DefineShortVerb | lstMakeShortInline  ) $no_corchete $delimitador /ix;
  58. my $indefinedel = qr/\\ (?: UndefineShortVerb | lstDeleteShortInline) $llaves                   /ix;
  59.  
  60. ## Cambiar
  61. while ($cuerpo =~
  62.         /   $marca
  63.         |   $comentario
  64.         |   $definedel
  65.         |   $indefinedel
  66.         |   $del .+? $del                                                       # delimitado
  67.         /pgmx) {
  68.  
  69.         my($pos_inicial, $pos_final) = ($-[0], $+[0]);                          # posiciones
  70.         my $encontrado = ${^MATCH};                                             # lo encontrado
  71.  
  72.     if ($encontrado =~ /$definedel/){                                           # definimos delimitador
  73.                         $del = $+{del};
  74.                         $del = "\Q$+{del}" if substr($del,0,1) ne '\\';         # es necesario "escapar" el delimitador
  75.                 }
  76.     elsif($encontrado =~ /$indefinedel/) {                                      # indefinimos delimitador
  77.                  $del = $no_del;                                       
  78.         }
  79.     else {                                                                      # aquí se hacen los cambios
  80.         while (my($busco, $cambio) = each %cambios) {
  81.                        $encontrado =~ s/\Q$busco\E/$cambio/g;                   # es necesario escapar $busco
  82.                         }
  83.         substr $cuerpo, $pos_inicial, $pos_final-$pos_inicial, $encontrado;     # insertamos los nuevos cambios
  84.  
  85.         pos($cuerpo)= $pos_inicial + length $encontrado;                        # re posicionamos la siguiente búsqueda
  86.         }
  87. }
  88.  
  89. ## Escritura del resultado
  90. open my $SALIDA, '>', "$name-out$ext";
  91. print   $SALIDA "$cabeza$cuerpo$final";
  92. close   $SALIDA;
  93.  
  94. __END__
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
y me gustaría añadir una nueva regla para que modifique las palabras que se encuentren entre otras dos, por ejemplo, si la entrada es de esta forma:
Sintáxis: [ Descargar ] [ Ocultar ]
Using latex Syntax Highlighting
  1. \documentclass{article}
  2. \usepackage{minted}
  3. \usepackage{pstricks-add}
  4. \newenvironment{postscript}{}{}
  5. \begin{document}
  6.  
  7. Usamos \verb|\begin{pspicture} o \begin{pspicture*}| o \verb*|\begin{pspicture} o \begin{pspicture*}| (cambia)
  8. esta línea debería quedar intacta \begin{pspicture} o \begin{pspicture*}
  9. % esta línea debería modificarse \begin{pspicture} o \begin{pspicture*}
  10.  
  11. %\begin{postscript} debería cambiar
  12. \begin{verbatim}
  13. \psset{unit=1.0cm}
  14. \begin{pspicture}[showgrid=true](4,2)
  15.   \psscaleboxto(8,2){foo bar baz}
  16. \end{pspicture}
  17. \end{verbatim}
  18.  TEXTO
  19. \begin{LTXexample}[algo=1,
  20.                                         algo=2]
  21. \begin{pspicture*}(4,2)(8,1)
  22. \psset{unit=1.0cm}
  23. \psscaleboxto(8,2){foo bar baz}
  24. \end{pspicture*}
  25. \end{LTXexample}
  26. TEXTO
  27. \begin{tcblisting}{colback=red!5!white,colframe=red!25,left=6mm,
  28. listing options={style=tcblatex,numbers=left,numberstyle=\tiny\color{red!75!black}}}
  29. \begin{postscript}[showgrid=true](4,2)
  30.   \psscaleboxto(8,2){foo bar baz}
  31. \end{postscript}
  32. \end{tcblisting}
  33. TEXTO
  34. \begin{mybox}[listing side text]
  35. {Listing Box}
  36. \psset{unit=1.0cm}
  37. \begin{pspicture}[showgrid=true](4,2)
  38.   \psscaleboxto(8,2){foo bar baz}
  39. \end{pspicture}
  40. \end{mybox}
  41. \end{document}
  42.  
  43. %\endpspicture o \end{pspicture} no debería cambiar
  44.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
la salida sea de esta forma:
Sintáxis: [ Descargar ] [ Ocultar ]
Using latex Syntax Highlighting
  1. \documentclass{article}
  2. \usepackage{minted}
  3. \usepackage{pstricks-add}
  4. \newenvironment{postscript}{}{}
  5. \begin{document}
  6.  
  7. Usamos \verb|\begin{TRICKS} o \begin{TRICKS*}| o \verb*|\begin{TRICKS} o \begin{TRICKS*}| (cambia)
  8. esta línea debería quedar intacta \begin{pspicture} o \begin{pspicture*}
  9. % esta línea debería modificarse \begin{TRICKS} o \begin{TRICKS*}
  10.  
  11. %\begin{POSTRICKS} debería cambiar
  12. \begin{verbatim}
  13. \psset{unit=1.0cm}
  14. \begin{TRICKS}[showgrid=true](4,2)
  15.   \psscaleboxto(8,2){foo bar baz}
  16. \end{TRICKS}
  17. \end{verbatim}
  18.  TEXTO
  19. \begin{LTXexample}[algo=1,
  20.                                         algo=2]
  21. \begin{TRICKS*}(4,2)(8,1)
  22. \psset{unit=1.0cm}
  23. \psscaleboxto(8,2){foo bar baz}
  24. \end{TRICKS*}
  25. \end{LTXexample}
  26. TEXTO
  27. \begin{tcblisting}{colback=red!5!white,colframe=red!25,left=6mm,
  28. listing options={style=tcblatex,numbers=left,numberstyle=\tiny\color{red!75!black}}}
  29. \begin{POSTRICKS}[showgrid=true](4,2)
  30.   \psscaleboxto(8,2){foo bar baz}
  31. \end{POSTRICKS}
  32. \end{tcblisting}
  33. TEXTO
  34. \begin{mybox}[listing side text]
  35. {Listing Box}
  36. \psset{unit=1.0cm}
  37. \begin{TRICKS}[showgrid=true](4,2)
  38.   \psscaleboxto(8,2){foo bar baz}
  39. \end{TRICKS}
  40. \end{mybox}
  41.  
  42. \end{document}
  43.  
  44. %\endpspicture o \end{pspicture} no debería cambiar
  45.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
es decir, que modifique las palabras si se encuentran entre las líneas que digan \begin{verbatim}, \begin{LTXexample}, \begin{tcblisting}, \begin{mybox} y \end{verbatim}, \end{LTXexample}, \end{tcblisting}, \end{mybox}. ¿Se puede modificar el script para lograr esto? o ¿debo crear otro que haga esta función?

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

Re: Acotar expresión regular

Notapor explorer » 2014-03-22 18:46 @823

En principio, habría que hacer una prueba ampliando el hash %cambios, pero sabiendo que esos cambios no tienen en cuenta la paridad de las marcas (si van parejas o no) o si están incluidas unas dentro de otras.

Si necesitas una comprobación más fuerte, lo mejor es hacer un programa nuevo.
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

Re: Acotar expresión regular

Notapor pablgonz » 2014-03-22 20:28 @894

Gracias por la respuesta, explorer, la verdad he analizado bastante lo que deseo hacer y ya tengo claras las condiciones de mi problema. La descripción es más menos así:
  • Usar el mismo hash ya definido (siempre son las mismas palabras las que deseo cambiar)
  • La paridad de las palabras entre las que deseo cambiar es necesaria y nunca van anidadas entre sí (incluidas unas dentro de otras), es decir, son siempre de la forma:
    Sintáxis: [ Descargar ] [ Ocultar ]
    Using latex Syntax Highlighting
    1. \begin{LTXexample}[aveces está presente con y sin saltos de línea]{a veces está presente con y sin saltos de línea} \s (obligatorio)
    2. Texto y palabras que deseo cambiar usando el hash.
    3. \end{LTXexample}
    Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
  • Crear una lista con las palabras que delimitan lo que deseo cambiar:
    Sintáxis: [ Descargar ] [ Ocultar ]
    Using perl Syntax Highlighting
    1. my $ENTORNO  = qr/(v|V)erbatim | (v|V)erbatim| LTXexample | tcblisting | mybox | otras/x;
    Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
  • Como ya tengo cargado el archivo en memoria, uso una expresión regular en $cuerpo y hago los cambios que deseo, algo como:
    Sintáxis: [ Descargar ] [ Ocultar ]
    Using perl Syntax Highlighting
    1. $cuerpo =~s/\A (.+? ^\\begin{$ENTORNO}?:\[ .+? \]?:\{ .+? \}\s) (lo que deseo cambiar usando el hash)(\\end{$ENTORNO})\z/$1$2$3/msxg;
    Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
En mi lógica es factible, ya tengo el archivo cargado y dividido en memoria pero no logro armar la idea dentro del bucle. Espero haberme explicado.

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

AnteriorSiguiente

Volver a Básico

¿Quién está conectado?

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