2010-07-13 23 views
5

Có cách nào để sử dụng biến làm công cụ sửa đổi thay thế không?Cách sử dụng biến làm công cụ sửa đổi thay thế

my $search = 'looking'; 
my $replace = '"find: $1 ="'; 
my $modifier = 'ee'; 

s/$search/$replace/$modifier; 

Tôi cần sử dụng một mảng băm để tìm kiếm hàng loạt thay thế bằng các công cụ sửa đổi khác nhau.

+9

Một số công cụ sửa đổi có thể được cung cấp bên trong regex dưới dạng '(? Modifier: pattern)' chứ không phải những thứ có hiệu lực như toàn bộ/g hoặc/e. Đây là một trong những khoảnh khắc "tại sao bạn làm điều đó". Nếu bạn nói với chúng tôi những gì này là cho, chúng tôi có thể có thể đến với một cách đơn giản hơn là đánh răng chống lại lạc đà (và mở một lỗ hổng bảo mật). – Schwern

+0

@Schwern: Và nó khó chịu nhất nếu bạn mở một lỗ trong lạc đà của bạn – Borodin

Trả lời

3

Hm, nếu tôi đã phải làm điều đó tôi sẽ làm như thế này:

use warnings; 
use strict; 
my @stuff = (
{ 
    search => "this", 
    replace => "that", 
    modifier => "g", 
}, 
{ 
    search => "ono", 
    replace => "wendy", 
    modifier => "i", 
} 
); 
$_ = "this ono boo this\n"; 
for my $h (@stuff) { 
    if ($h->{modifier} eq 'g') { 
     s/$h->{search}/$h->{replace}/g; 
    } elsif ($h->{modifier} eq 'i') { 
     s/$h->{search}/$h->{replace}/i; 
    } 
    # etc. 
} 
print; 

Chỉ có rất nhiều bổ khác nhau mà bạn có thể muốn sử dụng vì vậy tôi nghĩ rằng đây đủ dễ dàng.

Bạn có thể sử dụng eval để làm điều này, nhưng thật là lộn xộn.

+7

Lộn xộn là trong mắt của kẻ thù. Tôi thấy điều này lộn xộn hơn so với giải pháp eval. – runrig

+2

@runrig: "lộn xộn" trong trường hợp này không đề cập đến mã trông như thế nào. Có rất nhiều lỗi khó theo dõi bạn cần phải quan tâm nếu bạn sử dụng 'eval'. –

+0

Đây là giải pháp mà tôi đã suy nghĩ trước khi hỏi Stackoverflox. – bem33

4

Bạn có thể sử dụng eval, nếu bạn đeo kính an toàn và bộ đồ chia cho không.

Ví dụ:

use strict; 
use warnings; 
sub mk_re { 
    my ($search, $replace, $modifier) = @_; 
    $modifier ||= ''; 
    die "Bad modifier $modifier" unless $modifier =~ /^[msixge]*$/; 
    my $sub = eval "sub { s/($search)/$replace/$modifier; }"; 
    die "Error making regex for [$search][$replace][$modifier]: [email protected]" unless $sub; 
    return $sub; 
} 

my $search = 'looking'; 
my $replace = '"find: $1 ="'; 
my $modifier = 'e'; 

# Sub can be stored in an array or hash 
my $sub = mk_re($search, $replace, $modifier); 

$_ = "abc-looking-def"; 
print "$_\n"; 
$sub->(); 
print "$_\n"; 
+0

Bộ đồ phân chia theo số không của tôi có một lỗ trong nó xung quanh trừ vô cực – Borodin

4

Trong khi phương pháp sử dụng eval để biên dịch một thay mới có lẽ là đơn giản nhất, bạn có thể tạo thay người ở đó là nhiều mô-đun:

use warnings; 
use strict; 

sub subst { 
    my ($search, $replace, $mod) = @_; 

    if (my $eval = $mod =~ s/e//g) { 
     $replace = qq{'$replace'}; 
     $replace = "eval($replace)" for 1 .. $eval; 
    } else { 
     $replace = qq{"$replace"}; 
    } 
    sub {s/(?$mod)$search/$replace/ee} 
} 

my $sub = subst '(abc)', 'uc $1', 'ise'; 

local $_ = "my Abc string"; 

$sub->(); 

print "$_\n"; # prints "my ABC string" 

này chỉ được thử nghiệm nhẹ nhàng, và nó là trái như một bài tập để người đọc triển khai các cờ khác như g

+0

+1 Thông minh, miễn là các biện pháp phòng ngừa an ninh được thực hiện ... – dawg

+0

Có vẻ như đó là một cách tốt. Tôi sẽ xem thử. Cảm ơn. – bem33

+0

Tại sao có công cụ sửa đổi 'ee' trên mọi thay thế? – runrig

2

Tất nhiên s/$search/$replace/ hoạt động như bạn mong đợi. Đó là các công cụ sửa đổi động không đơn giản.

Đối với đối sánh thông thường modifiers của pimsx, bạn có thể sử dụng số Extended Patterns của Perl để sửa đổi cờ sửa đổi khi đang di chuyển như một phần của mẫu của bạn. Đây là các hình thức (?pimsx-imsx) để bật/tắt những sửa đổi.

Đối với các mẫu s//eee, bạn có thể sử dụng (?{ perl code}) được ghi lại trong cùng một phần. Đối với tất cả các hình thức evale hoặc ee, hãy xem xét tính bảo mật của mã kết quả!

Không có biểu mẫu nào để sửa đổi kết quả toàn cầu thành khớp đầu tiên mà tôi biết, do đó, so khớp toàn cầu và trận đấu đầu tiên sẽ cần phải là các phát biểu riêng biệt.

2

Đây là sự kết hợp giữa câu trả lời và đánh giá của Kinopiko.

eval được sử dụng ở đây để tạo bảng tra cứu theo kiểu được kiểm soát và bảo trì, và bảng tra cứu được sử dụng để lưu tất cả nếu .. elsif .. elsif không quá thú vị để xem.

(rất nhẹ thử nghiệm)

my @stuff = (
{ 
    search => "this", 
    replace => "that", 
    modifier => "g", 
}, 
{ 
    search => "ono", 
    replace => "wendy", 
    modifier => "i", 
} 
); 
$_ = "this ono boo this\n"; 

my @modifiers = qw{m s i x g e}; 

my $s_lookup = {}; 

foreach my $modifier (@modifiers) { 
    $s_lookup->{$modifier} = eval " sub { s/\$_[0]/\$_[1]/$modifier } "; 
} 

for my $h (@stuff) { 
    $s_lookup->{$h->{modifier}}->($h->{search},$h->{replace}); 
} 

print; 

Để được hoàn toàn hữu ích này cần:

  1. kết hợp các bộ điều chỉnh có thể
  2. loại chức năng trên bảng tra cứu để 'msi' kết hợp và 'mis 'kết hợp sẽ đi đến cùng một khóa.
+0

Hoặc chỉ cần thêm kiểm tra xác thực của trình sửa đổi vào câu trả lời eval khác, chẳng hạn như câu trả lời có ở đó. – runrig

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