2009-02-23 40 views
7

Tôi đang sử dụng chương trình Perl để trích xuất văn bản từ một tệp. Tôi có một mảng các chuỗi mà tôi sử dụng như delimiters cho các văn bản, ví dụ:Làm cách nào để xử lý các ký tự đặc biệt trong một regex Perl?

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

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

Tuy nhiên, hai trong số những chuỗi trong mảng là $450(Buy now). Vấn đề với các biểu tượng này là các ký hiệu trong các chuỗi biểu diễn kết thúc chuỗi và nhóm chụp trong các biểu thức chính quy Perl, do đó văn bản không phân tích cú pháp như tôi dự định.

Có cách nào khác không?

Trả lời

11

Thử chức năng quotemeta của Perl. Ngoài ra, hãy sử dụng \Q\E trong regex của bạn để tắt nội suy các giá trị trong regex. Xem perlretut để biết thêm thông tin về \Q\E - chúng có thể không phải là những gì bạn đang tìm kiếm.

+0

Cụ thể, \ Q sẽ không bảo vệ chống lại các ký tự thoát được dấu gạch chéo ngược. quotemeta là đến nay các giải pháp tổng quát hơn. –

+2

@ BenBlank: Bạn đang nói về cái gì? '\ Q' * biên dịch thành *' quotemeta'. Họ là những chức năng tương tự. Tương tự, '\ L' biên dịch thành' lc', '\ U' thành' uc', vv '\ Q'" bảo vệ chống lại "các ký tự thoát dấu chéo ngược hoàn toàn tốt, vì ** nó là' \ Q' sau khi tất cả! ** – tchrist

4

Sử dụng quotemeta:

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

quotemeta thoát meta-nhân vật để họ được giải thích như literals. Như một phím tắt, bạn có thể sử dụng \ Q ... \ E trong bối cảnh đúp quotish bao vây thứ mà nên được trích dẫn:

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

hoặc

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

hoặc chỉ

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

Lưu ý rằng điều này không bị giới hạn bởi các biến nội suy; ký tự chữ bị ảnh hưởng quá:

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

mặc dù rõ ràng là nó sẽ xảy ra sau khi suy biến, vì vậy "\ Q $ foo" không trở thành '\ $ foo'.

Các vấn đề liên quan