2010-04-19 23 views
7

Tôi bị nhức đầu tìm kiếm điều này: Bạn sử dụng s /// như thế nào trong một biểu thức trái ngược với một bài tập. Để làm rõ những gì tôi muốn nói, tôi đang tìm một tương đương perl của re.sub python của (...) khi được sử dụng trong bối cảnh sau đây:Tôi làm cách nào để sử dụng s /// của Perl trong một biểu thức?

newstring = re.sub('ab', 'cd', oldstring) 

Cách duy nhất tôi biết làm thế nào để làm điều này trong perl cho đến nay là:

$oldstring =~ s/ab/cd/; 
$newstring = $oldstring; 

Lưu ý việc gán thêm.

+4

dụ của bạn sẽ đặt cả '$ oldstring 'và' $ newstring' vào văn bản đã sửa đổi. Bạn có ý định thực hiện nhiệm vụ trước khi thay thế và sau đó thực hiện thay thế trên '$ newstring'? – mob

Trả lời

7

Dường như bạn có quan niệm sai về cách hoạt động của =~. =~ là toán tử liên kết liên kết biến với toán tử regexp. Nó không thực hiện bất kỳ nhiệm vụ nào.

Tất cả các toán tử regexp đều hoạt động theo mặc định với biến chủ đề $_, vì vậy s/foo/bar/; giống với $_ =~ s/foo/bar/;. Không có chuyển nhượng nào xảy ra. Biến chủ đề được chuyển đổi.

Trường hợp tương tự khi hoạt động trên bất kỳ biến nào khác. $var =~ s/foo/bar/; chuyển đổi $var bằng cách thay thế phiên bản đầu tiên của foo bằng bar. Không có chuyển nhượng nào xảy ra.

Lời khuyên tốt nhất tôi có thể cung cấp cho bạn là viết Python bằng Python và Perl trong Perl. Đừng mong đợi hai ngôn ngữ sẽ giống nhau.

Bạn có thể làm như DVK gợi ý và viết một chương trình con sẽ tái tạo hành vi thay thế mà bạn quen.

Hoặc bạn có thể thử một số thành ngữ Perl.Dựa trên mong muốn thể hiện của bạn để áp dụng nhiều phép biến đổi trong một dòng, tôi đã cung cấp một vài ví dụ bạn có thể thấy hữu ích.

Ở đây tôi sử dụng một vòng lặp for hơn một mục để topicalize $var và áp dụng nhiều biến đổi mã hóa cứng:

for($var) { 
    s/foo/bar/; 
    s/fizz/buzz/; 
    s/whop/bop-a-loo-bop/; 
    s/parkay/butter/; 
    s/cow/burger/; 
} 

Hoặc có thể bạn cần phải áp dụng một nhóm biến của biến đổi. Tôi định nghĩa một chương trình con để lặp qua một danh sách các tham chiếu mảng xác định các cặp chuyển đổi cũ/mới. Ví dụ này tận dụng lợi thế của xử lý đối số định hướng danh sách của Perl để xử lý bất kỳ số lần chuyển đổi nào.

my $foo = transform(
    'abcd' => 
    [ 'a', 'b' ], 
    [ 'bb', 'c' ], 
    [ 'cc', 'd' ], 
    [ 'dd', 'DONE' ], 
); 

sub transform { 
    my $var = shift; 
    for (@_) { 
     my ($old, $new) = @$_; 
     $var =~ s/$old/$new/; 
    } 

    return $var; 
} 

Cuối cùng một chút rối tung lên để cung cấp một phiên bản của chuyển đổi mà sửa đổi đối số đầu tiên của nó:

my $foo = 'abcd'; 

transform_in_place(
    $foo => 
    [ 'a', 'b' ], 
    [ 'bb', 'c' ], 
    [ 'cc', 'd' ], 
    [ 'dd', 'DONE' ], 
); 

print "$foo\n"; 

sub transform_in_place { 
    for my $i (1..$#_) { 
     my ($old, $new) = @{$_[$i]}; 
     $_[0] =~ s/$old/$new/; 
    } 
} 

Đối với dự án riêng của tôi, tôi có thể muốn sử dụng một trong hai tùy chọn đầu tiên tùy thuộc vào nhu cầu của vấn đề cụ thể.

11

Bạn có thể sử dụng ($new = $old) =~ s/whatever/whateverelse/; cho một chức năng chính xác mà bạn đang tìm kiếm:

use strict; 
my $old = "OLD"; 
my $new; 
($new = $old) =~ s/OLD/NEW/; 
print "old=$old, new=$new"; 

Tạo:

old=OLD, new=NEW 

Chính xác những gì bạn muốn

Nếu bạn đang tìm kiếm một chức năng , bạn chỉ có thể xác định của riêng mình để tránh chuyển nhượng:

use strict; 
sub re_sub { 
    my ($find, $replace, $old) = @_; 
    my $new = $old; 
    $new =~ s/$find/$replace/; 
    return $new; 
} 

my $old = "ab"; 
my $new = re_sub('ab', 'cd', $old); 
print "new=$new\n"; 

Kết quả trong new=cd.

7

Thay thế biểu thức chính quy của Perl luôn xảy ra 'tại chỗ'. Vì vậy, bạn cần phải sao chép chuỗi đến một biến mới và hoạt động trên biến mới:

(my $newstring = $oldstring) =~ s/ab/cd/; 
+1

Dựa trên điều này, tôi có quyền giả định rằng bạn * không thể * có hai s /// trong một dòng, một trong số đó sử dụng kết quả của người khác, không có bài tập trung gian không? – Mansour

+1

Trong khi bạn có thể đạt được điều đó bằng cách thêm dấu ngoặc đơn và = ~ vào cuối, thì không có cú pháp rõ ràng cho nó. –

2

Bạn muốn có $ newstring thể là kết quả của sự thay thế này, phải không?

Something như thế này:

($newstring = $oldstring) =~ s/ab/cd; 

nên làm việc. Bộ chuyển nhượng $newstring đến $oldstring và sau đó đánh giá là $newstring, đó là những gì mà hành vi thay thế diễn ra.

1

Dựa trên điều này, tôi có quyền giả định rằng bạn không thể có hai s /// trong một dòng, một trong số đó sử dụng kết quả của người khác, không có bài tập trung gian không? - mikeY

Có bạn là chính xác. Nếu bạn muốn áp dụng nhiều thay vào chuỗi cùng tôi sẽ làm

$newstring = $oldstring ; 
    $newstring =~ s/ab/cd/ ; 
    $newstring =~ s/xx/yy/ ; 

Sau đây sẽ không làm việc vì s// trả về số lần thay người thực hiện, không phải là thay đổi chuỗi.

$newstring = $oldstring) =~ s/ab/cd/ =~ s/xx/yy/ ; 

Tóm lại, hoạt động regex Perl của tôi rất khác nhau để Python và bạn đang cố gắng tốt hơn để tìm hiểu những gì Perl thực hiện từ đầu thay vì cố gắng để lập bản đồ khái niệm Python vào Perl

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