2009-02-09 12 views
7

Mam program Perl, który przechowuje wyrażenia regularne w plikach konfiguracyjnych. Są one w formie:Podwójna interpolacja wyrażeń regularnych w Perlu

regex = ^/d+$ 

indziej, regex pobiera analizowany z pliku i przechowywane w zmiennej - $regex. Następnie używam zmiennej podczas sprawdzania wyrażeń regularnych, np.

$lValid = ($valuetocheck =~ /$regex/); 

Chcę móc uwzględnić zmienne perl w pliku konfiguracyjnym, np.

regex = ^\d+$stored_regex$ 

Ale nie mogę się dowiedzieć, jak to zrobić.

Gdy wyrazy regularne są analizowane przez Perla, interpretowane są dwa razy. Najpierw zmienne są rozwijane, a następnie przetwarzane jest wyrażenie regularne.

Potrzebuję trzystopniowego procesu: Najpierw interpoluj $regex, następnie interpoluj zmienne, które zawiera, a następnie przeanalizuj wynikowe wyrażenie regularne. Obie pierwsze interpolacje muszą mieć "świadomość regularną". na przykład powinni wiedzieć, że ciąg zawiera $ jako kotwica itp ...

Jakieś pomysły?

Odpowiedz

3

Za pomocą eval można w tym miejscu pomóc. Spójrz na poniższy kod może precompile regexp, który jest gotowy do użycia ostatnia: QR

my $compiled_regexp; 
my $regexp = '^\d+$stored_regexp$'; 
my $stored_regexp = 'a'; 

eval "\$compiled_regexp = qr/$regexp/;"; 
print "$compiled_regexp\n"; 

Operator // może być używany do precompile regexp. Pozwala na zbudowanie, ale jeszcze go nie uruchamia. Możesz najpierw zbudować zaimki regexps, a następnie użyć ich później.

3

Twoje zmienne Perla nie znajdują się w twoim pliku konfiguracyjnym i myślę, że to dobrze. eval jest przerażający.

Lepiej będzie, jeśli skorzystasz z własnego szablonu.

Więc w pliku konfiguracyjnym:

regex = ^\d+__TEMPLATE_FIELD__$ 

w czytniku plików config:

# something like this for every template field you need 
$regex =~ s/__TEMPLATE_FIELD__/$stored_regex/g; 

Podczas korzystania:

$lValid = ($valuetocheck =~ m/$regex/) 

przenieść te okolice w zależności w jakim punkcie chcesz Zastąpienie szablonu.

7

Można zdefiniować wyrażenia regularnego w pliku konfiguracyjnym jak ten:

regex = ^\d+(??{$stored_regex})$ 

Ale trzeba będzie wyłączyć kontrolę bezpieczeństwa w bloku, w którym używasz regexp robiąc to w programie Perl:

use re 'eval'; 
+1

To eleganckie rozwiązanie. –

0

stycznie związane haczyka: Jeśli to podwójne interpolacji inline, a także ciągi zastępcze zmiennych, należy rozważyć:

# the concat with doublequotes in the replacement string 
# are to make them PART OF THE STRING, NOT THE STRING DELIMITERS, 
# in other words, so the 2nd interpolation sees a double quoted string : 
#  eval eval $replace -> eval $1 hello world -> syntax error 
#  eval eval $replace -> eval "$1 hellow world" -> works ok 
# see: http://www.perlmonks.org?node_id=687031 

if($line =~ s/$search/'"' . $replace . '"'/ee) { 
    # STUFF... 
} 
Powiązane problemy