2013-05-30 30 views
8

Có cách nào để thay thế nhiều chuỗi trong chuỗi không? Ví dụ, tôi có chuỗi hello world what a lovely day và tôi muốn thay thế whatlovely với cái gì khác ..Perl thay thế nhiều chuỗi đồng thời

$sentence = "hello world what a lovely day"; 
@list = ("what", "lovely"); # strings to replace 
@replist = ("its", "bad"); # strings to replace with 
($val = $sentence) =~ "tr/@list/@replist/d"; 
print "$val\n"; # should print "hello world its a bad day".. 

Bất cứ ý tưởng tại sao nó không làm việc?

Cảm ơn.

+0

Từ có luôn là toàn bộ từ hoặc có tiềm năng cho mẫu không? – squiguy

Trả lời

9

Trước hết, tr không hoạt động theo cách đó; tham khảo perldoc perlop để biết chi tiết, nhưng tr thực hiện chuyển ngữ và rất khác với thay thế.

Đối với mục đích này, một cách chính xác hơn để thay thế sẽ là

# $val 
$val =~ s/what/its/g; 
$val =~ s/lovely/bad/g; 

Lưu ý rằng "đồng thời" thay đổi là khá khó khăn hơn, nhưng chúng ta có thể làm điều đó, ví dụ,

%replacements = ("what" => "its", "lovely" => "bad"); 
($val = $sentence) =~ s/(@{[join "|", keys %replacements]})/$replacements{$1}/g; 

(Dĩ nhiên, việc thoát ra có thể cần thiết để thay thế các chuỗi bằng các siêu ký tự.)

Điều này vẫn chỉ đồng thời theo nghĩa rất lỏng lẻo, nhưng nó có, cho hầu hết các mục đích, ac t như thể thay thế được thực hiện trong một lần.

Ngoài ra, thay thế "what" bằng "it's", thay vì "its" cũng chính xác hơn.

6

Vâng, chủ yếu là nó không hoạt động như tr///d không liên quan gì đến yêu cầu của bạn (tr/abc/12/d thay thế bằng 1, b bằng 2 và loại bỏ c). Ngoài ra, theo các mảng mặc định không nội suy thành các cụm từ thông dụng theo cách hữu ích cho tác vụ của bạn. Ngoài ra, không có thứ gì đó giống như tra cứu băm hoặc cuộc gọi chương trình con hoặc logic khác, bạn không thể đưa ra quyết định ở bên phải của hoạt động s///.

Để trả lời câu hỏi trong tiêu đề, bạn có thể thực hiện nhiều Thay thế đồng thời - er, liên tiếp thuận tiện - theo cách này:

#! /usr/bin/env perl 
use common::sense; 

my $sentence = "hello world what a lovely day"; 

for ($sentence) { 
    s/what/it's/; 
    s/lovely/bad/ 
} 

say $sentence; 

Để làm được một cái gì đó giống như những gì bạn cố gắng ở đây:

#! /usr/bin/env perl 
use common::sense; 

my $sentence = "hello world what a lovely day"; 

my %replace = (
    what => "it's", 
    lovely => 'bad' 
); 

$sentence =~ s/(@{[join '|', map { quotemeta($_) } keys %replace]})/$replace{$1}/g; 

say $sentence; 

Nếu bạn sẽ được làm rất nhiều thay thế như vậy, 'biên dịch' regex đầu tiên:

my $matchkey = qr/@{[join '|', map { quotemeta($_) } keys %replace]}/; 

... 

$sentence =~ s/($matchkey)/$replace{$1}/g; 

EDIT:

Và để mở rộng nhận xét của tôi về mảng nội suy, bạn có thể thay đổi $":

local $" = '|'; 
$sentence =~ s/(@{[keys %replace]})/$replace{$1}/g; 
# --> $sentence =~ s/(what|lovely)/$replace{$1}/g; 

Mà không cải thiện tình hình ở đây, thực sự, mặc dù nó có thể nếu bạn đã có các phím trong một mảng:

local $" = '|'; 
$sentence =~ s/(@keys)/$replace{$1}/g; 
Các vấn đề liên quan