2010-02-21 31 views
56

Tôi đang cố gắng sử dụng regex trong Perl. Những gì tôi đã tự hỏi là nếu nó có thể lưu trữ tất cả các trận đấu với biểu thức thành một mảng? Tôi biết tôi có thể sử dụng như sau: ($1,...,$n) = m/expr/g; nhưng có vẻ như là chỉ có thể được sử dụng nếu bạn biết số lượng phù hợp bạn đang tìm kiếm. Tôi đã thử my @array = m/expr/g; nhưng điều đó dường như không hoạt động.Làm thế nào tôi có thể lưu trữ ảnh chụp regex trong một mảng trong Perl?

Cảm ơn sự giúp đỡ của bạn!

+8

giải thích "doesn dường như không hoạt động ", tốt nhất là với một ví dụ thực tế. Cần làm việc. – ysth

Trả lời

70

Nếu bạn đang thực hiện kết hợp toàn cầu (/g) thì regex trong ngữ cảnh danh sách sẽ trả về tất cả các kết quả phù hợp đã chụp. Đơn giản chỉ cần làm:

my @matches = ($str =~ /pa(tt)ern/g) 

Lệnh này ví dụ:

perl -le '@m = ("foo12gfd2bgbg654" =~ /(\d+)/g); print for @m' 

Cung cấp đầu ra:

12 
2 
654 
+10

không cần cho(), = ~ là toán tử ưu tiên cao – ysth

+3

Hãy chắc chắn sử dụng "nếu bạn thử điều này trong cửa sổ 'vỏ', như thế này, perl -le" @m = ('foo12gfd2bgbg654' = ~/(\ d +)/g); in cho @m "nếu không bạn sẽ gặp lỗi, vì trình bao sử dụng" làm dấu phân tách chuỗi – roamcel

+10

@ysth. Nó ít dễ đọc hơn nếu không có dấu ngoặc đơn. – MikeKulls

15

Xem bài hướng dẫn về perldoc perlop dưới "Matching tại Danh mục ngữ cảnh":

Nếu tùy chọn/g không được sử dụng, m // in ngữ cảnh danh sách trả về một danh sách bao gồm các biểu thức con phù hợp với dấu ngoặc đơn trong mẫu, tức là ($ 1, $ 2, $ 3 ...)

Trình sửa đổi/g chỉ định khớp mẫu toàn cục - nghĩa là, khớp với nhiều lần như có thể trong chuỗi. Cách hoạt động của nó phụ thuộc vào ngữ cảnh. Trong ngữ cảnh danh sách, nó trả về một danh sách các chất nền khớp với bất kỳ dấu ngoặc đơn nào trong biểu thức chính quy. Nếu không có dấu ngoặc đơn, nó sẽ trả về một danh sách tất cả các chuỗi phù hợp, như thể có dấu ngoặc đơn xung quanh toàn bộ mẫu.

Bạn chỉ có thể lấy tất cả các trận đấu bằng cách gán cho một mảng, hoặc nếu không thực hiện việc đánh giá trong danh sách bối cảnh:

my @matches = ($string =~ m/word/g); 
16

Đôi khi bạn cần để có được tất cả các trận đấu trên toàn thế giới, như PHP preg_match_all làm. Nếu đó là trường hợp của bạn, sau đó bạn có thể viết một cái gì đó như:

# a dummy example 
my $subject = 'Philip Fry Bender Rodriguez Turanga Leela'; 
my @matches; 
push @matches, [$1, $2] while $subject =~ /(\w+) (\w+)/g; 

use Data::Dumper; 
print Dumper(\@matches); 

It in

$VAR1 = [ 
      [ 
      'Philip', 
      'Fry' 
      ], 
      [ 
      'Bender', 
      'Rodriguez' 
      ], 
      [ 
      'Turanga', 
      'Leela' 
      ] 
     ]; 
+3

Kỹ thuật rất tiện dụng; có cách nào để khái quát hóa điều này, trong trường hợp số lượng các nhóm nắm bắt không được biết? – mklement0

8

Tôi nghĩ rằng đây là một ví dụ tự giải thích. Lưu ý /g modifier trong regex đầu tiên:

$string = "one two three four"; 

@res = $string =~ m/(\w+)/g; 
print Dumper(@res); # @res = ("one", "two", "three", "four") 

@res = $string =~ m/(\w+) (\w+)/; 
print Dumper(@res); # @res = ("one", "two") 

Hãy nhớ rằng, bạn cần phải chắc chắn vế trái là trong bối cảnh danh sách, có nghĩa là bạn phải bao quanh các giá trị vô hướng với ngoặc:

($one, $two) = $string =~ m/(\w+) (\w+)/; 
Các vấn đề liên quan