2010-04-17 43 views
5

Trong perl giả sử tôi có một chuỗi như 'hello\tworld\n', và những gì tôi muốn là:Làm cách nào tôi có thể nội suy thủ công chuỗi thoát trong chuỗi Perl?

'hello world 
' 

Đó là, "hello", sau đó một ký tự tab đen, sau đó "thế giới", sau đó một dòng mới theo nghĩa đen. Hoặc tương đương, "hello\tworld\n" (lưu ý các dấu ngoặc kép).

Nói cách khác, có chức năng lấy chuỗi có chuỗi thoát và trả về một chuỗi tương đương với tất cả các chuỗi thoát được nội suy không? Tôi không muốn nội suy các biến hoặc bất kỳ thứ gì khác, chỉ cần thoát khỏi các chuỗi như \x, trong đó x là một chữ cái.

Trả lời

8

Âm thanh như một vấn đề mà người khác sẽ phải solved already. Tôi chưa bao giờ sử dụng mô-đun, nhưng có vẻ hữu ích:

use String::Escape qw(unbackslash); 
my $s = unbackslash('hello\tworld\n'); 
+0

Cảm ơn rất nhiều vì điều này. Tôi tìm thấy String :: Interpolate, nhưng điều đó làm một cái gì đó hoàn toàn khác nhau. –

+0

Ngoài ra, đối với những người sử dụng tính năng này trong Ubuntu 9.10, phiên bản String :: Escape không có 'unbackslash'. Thay vào đó nó có 'unprintable'. –

2

Bạn có thể làm điều đó với 'eval':

my $string = 'hello\tworld\n'; 
my $decoded_string = eval "\"$string\""; 

Lưu ý rằng có những vấn đề an ninh gắn liền với cách tiếp cận rằng nếu bạn không có quyền kiểm soát 100% của chuỗi đầu vào.

Edit: Nếu bạn muốn CHỈ suy \ x thay thế (và không phải là trường hợp chung của 'bất cứ điều gì Perl sẽ suy trong một chuỗi trích dẫn'), bạn có thể làm điều này:

my $string = 'hello\tworld\n'; 
$string =~ s#([^\\A-Za-z_0-9])#\\$1#gs; 
my $decoded_string = eval "\"$string\""; 

Điều đó không gần như giống nhau điều như quotemeta - nhưng cố gắng thoát khỏi các ký tự '\'.

Edit2: Đây vẫn không phải là 100% an toàn vì nếu ký tự cuối cùng là một '\' - nó sẽ 'rò rỉ' quá khứ cuối chuỗi mặc dù ...

Cá nhân, nếu tôi muốn được an toàn 100% tôi sẽ làm một hash với các tàu ngầm tôi đặc biệt muốn và sử dụng một thay regex thay vì một eval:

my %sub_strings = (
    '\n' => "\n", 
    '\t' => "\t", 
    '\r' => "\r", 
); 

$string =~ s/(\\n|\\t|\\n)/$sub_strings{$1}/gs; 
+0

Tôi có thể sử dụng kết hợp 'eval' và' quotemeta' để thực hiện việc này một cách an toàn không? Về cơ bản, '(my $ interpolated_string = eval (q ("). Quotemeta ($ string). Q ("))) = ~ s/\\ (.)/\ 1/g'. –

+0

Không phải không có nó giết chết nội suy là tốt. ;) – Snowhare

+0

Vâng, tôi chỉ muốn nội suy '\ x', trong đó' x' là bất kỳ chữ cái nào. Không phải biến hoặc các thứ khác. –

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