2009-02-23 14 views
7

Używam programu Perl do wyodrębniania tekstu z pliku. Muszę szereg strun, które używać jako ograniczniki dla tekstu, na przykład:Jak obsługiwać znaki specjalne w wyrażeniu regularnym Perla?

$pat = $arr[1] . '(.*?)' . $arr[2]; 

if ($src =~ /$pat/) { 
    print $1; 
} 

jednak, dwóch łańcuchów w tablicy są $450 i (Buy now). Problem polega na tym, że symbole w łańcuchach reprezentują łańcuch końcowy i grupę przechwytywania w wyrażeniach regularnych Perla, więc tekst nie parsuje tak, jak zamierzam.

Czy istnieje sposób obejścia tego?

Odpowiedz

11

Spróbuj funkcji Perla za quotemeta. Możesz też użyć w wyrażeniu regularnym opcji \Q i \E, aby wyłączyć interpolację wartości w regex. Więcej informacji na temat perlretut na \Q i \E - mogą one nie być tym, czego szukasz.

+0

W szczególności \ Q nie będzie chroniło przed znakami uciekającymi ukośnikiem odwrotnym. quotemeta jest zdecydowanie bardziej ogólnym rozwiązaniem. –

+2

@BenBlank: O czym ty mówisz? '\ Q' * kompiluje się do *' quotemeta'. Są to ta sama funkcja. Podobnie, '\ L' kompiluje się do' lc', '\ U' do' uc', itd. '\ Q'" znakomicie chroni przed znakami "uciekającymi z ukośnikiem", ponieważ ** w końcu jest '\ Q'! ** – tchrist

4

Zastosowanie quotemeta:

$pat = quotemeta($arr[1]).'(.*?)'.quotemeta($arr[2]); 
if($src=~$pat) print $1; 
9

quotemeta ucieka metaznakami więc są one interpretowane jako literały. Jako skrót, można użyć \ Q ... \ E w podwójnym cytowaniu kontekście otoczyć rzeczy, które powinny być cytowane:

$pat = quotemeta($arr[1]).'(.*?)'.quotemeta($arr[2]); 
if($src=~$pat) { print $1 } 

lub

$pat = "\Q$arr[1]\E(.*?)\Q$arr[2]"; # \E not necessary at the end 
if($src=~$pat) { print $1 } 

lub po prostu

if ($src =~ /\Q$arr[1]\E(.*?)\Q$arr[2]/) { print $1 } 

Należy zauważyć, że nie jest to ograniczone do zmiennych interpolowanych; Znaki literalne wpływa też:

perl -wle'print "\Q.+?"' 
\.\+\? 

choć oczywiście zdarza się po zmiennej interpolacji, więc "\ Q $ foo" nie stać '\ $ foo'.

Powiązane problemy