2010-07-14 8 views
7

Así que estoy escribiendo un script rápido de Perl que limpia algunos códigos HTML y los ejecuta a través de un programa html -> pdf. Quiero perder la menor cantidad de información posible, por lo que me gustaría ampliar mis áreas de texto para que se ajusten a todo el texto que se encuentra actualmente en ellas. Esto significa, en mi caso, establecer el número de filas en un valor calculado en función del valor de la cadena dentro del cuadro de texto.Evaluaciones de incrustación en Perl regex

Esta es actualmente la expresión regular que estoy usando

$file=~s/<textarea rows="(.+?)"(.*?)>(.*?)<\/textarea>/<textarea rows="(?{ length($3)/80 })"$2>$3<\/textarea>/gis; 

Desafortunadamente no parece estar reconociendo Perl lo que me dijeron era la sintaxis para incrustar código Perl dentro de búsqueda y reemplazo regexs ¿Hay ¿Algun de los adictos a Perl que están dispuestos a decirme lo que estoy haciendo mal? Saludos, Zach

Respuesta

11

El patrón (?{...}) es una característica experimental para ejecutar el código en el lado de la coincidencia, pero desea ejecutar el código en el reemplazo lado. Utilice el interruptor /e-expresión regular para que:

#! /usr/bin/perl 

use warnings; 
use strict; 

use POSIX qw/ ceil /; 

while (<DATA>) { 
    s[<textarea rows="(.+?)"(.*?)>(.*?)</textarea>] { 
    my $rows = ceil(length($3)/80); 
    qq[<textarea rows="$rows"$2>$3</textarea>]; 
    }egis; 
    print; 
} 

__DATA__ 
<textarea rows="123" bar="baz">howdy</textarea> 

Salida:

<textarea rows="1" bar="baz">howdy</textarea>
0

creo que su problema es una sin escapar /

Si no es el problema, sin duda es un problema.

probar este lugar, tenga en cuenta el \/80

$file=~s/<textarea rows="(.+?)"(.*?)>(.*?)<\/textarea>/<textarea rows="(?{ length($3)\/80 })"$2>$3<\/textarea>/gis; 

El patrón básico para este código es:

$file =~ s/some_search/some_replace/gis; 

El gis son opciones, que me gustaría tener que mirar hacia arriba. Creo que g = global, i = caso insensible, s = nada viene a la mente en este momento.

+0

Un drogadicto de Perl, que no soy. Sin embargo, pensé que trabajaría en eso. –

1

¿Se debe hacer esto con expresiones regulares? Analizar cualquier lenguaje de marcado (o incluso CSV) con expresiones regulares está plagado de errores. Si puede, trate de utilizar una biblioteca estándar:

http://search.cpan.org/dist/HTML-Parser/Parser.pm

De lo contrario corre el riesgo de la venganza de Cthulu:

http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html

(Sí, el artículo deja espacio para algunas simples de manipulación de cadenas , así que creo que su alma está a salvo, sin embargo. :-)

5

La sintaxis que se utiliza para incrustar código sólo es válido en la parte de "juego" de la sustitución (la mano izquierda lado). Para incrustar el código en el lado derecho (que es un Perl normal de cadena entre comillas dobles), usted puede hacer esto:

$file =~ s{<textarea rows="(.+?)"(.*?)>(.*?)</textarea>} 
      {<textarea rows="@{[ length($3)/80 ]}"$2>$3</textarea>}gis; 

Este utiliza el lenguaje Perl de "some string @{[ embedded_perl_code() ]} more string".

Pero si se está trabajando con una declaración muy compleja, puede ser más fácil poner la sustitución en el modo de "eval", donde se trata la cadena de reemplazo como código de Perl:

$file =~ s{<textarea rows="(.+?)"(.*?)>(.*?)</textarea>} 
      {'<textarea rows="' . (length($3)/80) . qq{"$2>$3</textarea>}}gise; 

Nótese que en ambos ejemplos la expresión regular está estructurada como s{}{}. Esto no solo elimina la necesidad de escapar de las barras, sino que también le permite extender la expresión en varias líneas para facilitar su lectura.

0

En primer lugar, debe citar el / dentro de la expresión en el texto de reemplazo (de lo contrario, perl verá un operador s /// seguido del número 80 y así sucesivamente). O puede usar un delimitador diferente; para sustituciones complejas, los corchetes coincidentes son una buena idea.

Luego se llega al problema principal, que es que (?{...}) solo está disponible en patrones. El texto de reemplazo no es un patrón, es (casi) una cadena ordinaria.

En su lugar, existe el modificador e para el operador s///, que le permite escribir una expresión de reemplazo en lugar de una cadena de reemplazo.

 
$file =~ s(<textarea rows="(.+?)"(.*?)>(.*?)</textarea>) 
      ("<textarea rows=\"" . (length($3)/80) . "\"$2>$3</textarea>")egis; 
0

Según http://perldoc.perl.org/perlrequick.html#Search-and-replace, esto se puede lograr con el "modificador de la evaluación s///e", por ejemplo, que gis debe tener un extra e en ella.

El modificador de evaluación s /// e ajusta un eval {...} alrededor de la cadena de reemplazo y el resultado evaluado sustituye a la subcadena coincidente. Algunos ejemplos:

# convert percentage to decimal 
$x = "A 39% hit rate"; 
$x =~ s!(\d+)%!$1/100!e;  # $x contains "A 0.39 hit rate" 
Cuestiones relacionadas