2010-07-14 12 views
7

Quindi sto scrivendo un rapido script perl che pulisce del codice HTML e lo esegue attraverso un programma html -> pdf. Voglio perdere meno informazioni possibili, quindi mi piacerebbe estendere le mie aree di testo per adattarle a tutto il testo attualmente in esse contenuto. Ciò significa, nel mio caso, l'impostazione del numero di righe su un valore calcolato in base al valore della stringa all'interno della casella di testo.Incorporamento di valutazioni in Perl regex

Questo è attualmente l'espressione regolare che sto utilizzando

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

Purtroppo Perl non sembra essere riconoscere ciò che mi è stato detto era la sintassi per l'incorporamento codice Perl all'interno di ricerca e sostituzione regexs Esistono tutti i drogati di Perl là fuori disposti a dirmi cosa sto facendo di sbagliato? Saluti, Zach

risposta

11

Il pattern (?{...}) è una funzionalità sperimentale per l'esecuzione di codice sul lato della corrispondenza, ma si desidera eseguire il codice su il lato sostituzione. Usare l'interruttore /e espressioni regolari per questo:

#! /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> 

uscita:

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

Credo che il vostro problema è un escape /

Se non è il problema, è certamente un problema.

Prova a modificare, annotare il \/80

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

Il modello di base per questo codice è:

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

Il gis sono opzioni, che io avrei dovuto guardare in alto. Penso che g = global, i = case insensitive, s = non ti viene in mente niente in questo momento.

+0

un drogato perl, io non sono. Però, ho pensato di lavorarci su. –

1

Deve essere eseguito con regex? L'analisi di qualsiasi linguaggio di markup (o anche CSV) con regex è irto di errori. Se potete, cercate di utilizzare una libreria standard:

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

In caso contrario si rischia la vendetta di Cthulu:

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

(Sì, l'articolo lascia spazio a qualche semplice stringa di manipolazione , quindi penso che la tua anima sia al sicuro, però. :-)

5

La sintassi che si utilizza per incorporare codice è valido solo nella parte di "match" della sostituzione (la mano sinistra lato). Per incorporare il codice nel lato destro della strada (che è una normale stringa Perl double citato), si può fare questo:

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

Questo utilizza il linguaggio Perl di "some string @{[ embedded_perl_code() ]} more string".

Ma se si sta lavorando con una dichiarazione molto complessa, può essere più facile mettere la sostituzione in modalità "eval", dove si considera la stringa di sostituzione come codice Perl:

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

Si noti che in entrambi i esempi la regex è strutturata come s{}{}. Ciò non solo elimina la necessità di sfuggire alle barre, ma consente anche di diffondere l'espressione su più righe per renderla leggibile.

0

Innanzitutto, è necessario citare l'espressione / all'interno del testo sostitutivo (altrimenti perl verrà visualizzato l'operatore s /// seguito dal numero 80 e così via). Oppure puoi usare un delimitatore diverso; per sostituzioni complesse, le parentesi corrispondenti sono una buona idea.

Quindi si arriva al problema principale, ovvero che (?{...}) è disponibile solo nei modelli. Il testo sostitutivo non è un modello, è (quasi) una stringa ordinaria.

Invece, c'è il modificatore e per l'operatore s///, che consente di scrivere un'espressione sostitutiva anziché una stringa sostitutiva.

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

Secondo http://perldoc.perl.org/perlrequick.html#Search-and-replace, questo può essere realizzato con il "valutazione modificatore s///e", per esempio, è necessario disporre di gis un extra e in esso.

Il modificatore di valutazione s /// e racchiude una valutazione {...} attorno alla stringa di sostituzione e il risultato valutato è sostituito dalla sottostringa corrispondente. Alcuni esempi:

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