2010-02-14 36 views
13

Tôi có một regex:Làm cách nào để lưu trữ các ảnh chụp từ biểu thức chính quy Perl vào các biến riêng biệt?

/abc(def)ghi(jkl)mno(pqr)/igs 

Làm thế nào tôi có thể nắm bắt được kết quả của mỗi ngoặc vào 3 biến khác nhau, một cho mỗi dấu ngoặc đơn? Ngay bây giờ tôi sử dụng một mảng để nắm bắt tất cả các kết quả, chúng xuất hiện tuần tự nhưng sau đó tôi phải phân tích chúng và danh sách có thể rất lớn.

@results = ($string =~ /abc(def)ghi(jkl)mno(pqr)/igs); 
+0

Bạn có muốn đếm số lần mẫu được khớp không? Đó là những gì nó có vẻ như với tôi ... – Zaid

+0

tôi cần phải xử lý các trận đấu – Incognito

Trả lời

14

Câu hỏi của bạn là một chút mơ hồ với tôi, nhưng tôi nghĩ rằng bạn muốn làm một cái gì đó như thế này:

my (@first, @second, @third); 
while(my ($first, $second, $third) = $string =~ /abc(def)ghi(jkl)mno(pqr)/igs) { 
    push @first, $first; 
    push @second, $second; 
    push @third, $third; 
} 
+0

Thú vị. Bạn có chắc chắn rằng sẽ làm việc? – joejoeson

+3

hơi dài một chút. khi bị bắt, bạn có thể sử dụng tham khảo ngược – ghostdog74

+4

ghostdog74: đó là vấn đề về hương vị. Nếu bạn thực sự đặt tên biến $ đầu tiên và $ giây thì bạn cũng có thể sử dụng $ 1 và $ 2, nhưng nếu bạn cung cấp cho họ nhiều tên mô tả hơn thì nó có thể cải thiện khả năng đọc để làm như thế này. –

0

Bạn có thể có ba khác nhau regex của mỗi tập trung vào các nhóm cụ thể. Rõ ràng, bạn chỉ muốn chỉ định các nhóm khác nhau cho các mảng khác nhau trong regex, nhưng tôi nghĩ rằng tùy chọn duy nhất của bạn là chia regex lên.

2

@OP, khi ngoặc được chụp, bạn có thể sử dụng các biến $ 1, $ 2 .... đây là những backreferences

$string="zzzabcdefghijklmnopqrsssszzzabcdefghijklmnopqrssss"; 
while ($string =~ /abc(def)ghi(jkl)mno(pqr)/isg) { 
    print "$1 $2 $3\n"; 
} 

đầu ra

$ perl perl.pl 
def jkl pqr 
def jkl pqr 
+3

Lưu ý việc sử dụng công cụ sửa đổi g. Anh ấy đang làm một trận đấu toàn cầu, vì vậy tôi cho rằng anh ấy muốn lưu trữ nhiều trận đấu. –

+2

Ngoài ra, $ 1 và như vậy không phải là "backreferences", chúng được chụp. Tuy nhiên, dấu ngoặc đơn và backreferences là * có liên quan *. – jrockway

3

Một cách thay thế để làm việc đó sẽ trông như câu trả lời của ghostdog74, nhưng sử dụng mảng lưu trữ các tham chiếu băm:

my @results; 
while($string =~ /abc(def)ghi(jkl)mno(pqr)/igs) { 
    my ($key1, $key2, $key3) = ($1, $2, $3); 
    push @results, { 
     key1 => $key1, 
     key2 => $key2, 
     key3 => $key3, 
    }; 
} 

# do something with it 

foreach my $result (@results) { 
    print "$result->{key1}, $result->{key2}, $result->{key3}\n"; 
} 

với lợi thế chính ở đây sử dụng một cấu trúc dữ liệu duy nhất, VÀ có một vòng lặp có thể đọc được tốt đẹp.

5

Bắt đầu với 5.10, bạn có thể sử dụng named capture buffers cũng như:

#!/usr/bin/perl 

use strict; use warnings; 

my %data; 

my $s = 'abcdefghijklmnopqr'; 

if ($s =~ /abc (?<first>def) ghi (?<second>jkl) mno (?<third>pqr)/x) { 
    push @{ $data{$_} }, $+{$_} for keys %+; 
} 

use Data::Dumper; 
print Dumper \%data; 

Output:

$VAR1 = { 
      'first' => [ 
         'def' 
        ], 
      'second' => [ 
         'jkl' 
         ], 
      'third' => [ 
         'pqr' 
        ] 
     };

Đối với phiên bản trước, bạn có thể sử dụng sau đây mà tránh được việc phải thêm một dòng cho mỗi bị bắt bộ đệm:

#!/usr/bin/perl 

use strict; use warnings; 

my $s = 'abcdefghijklmnopqr'; 

my @arrays = \ my(@first, @second, @third); 

if (my @captured = $s =~ /abc (def) ghi (jkl) mno (pqr) /x) { 
    push @{ $arrays[$_] }, $captured[$_] for 0 .. $#arrays; 
} 

use Data::Dumper; 
print Dumper @arrays; 

Đầu ra:

$VAR1 = [ 
      'def' 
     ]; 
$VAR2 = [ 
      'jkl' 
     ]; 
$VAR3 = [ 
      'pqr' 
     ];

Nhưng tôi thích giữ dữ liệu liên quan trong một cấu trúc dữ liệu duy nhất, vì vậy tốt nhất bạn nên quay lại sử dụng hàm băm. Điều này đòi hỏi một mảng phụ trợ, tuy nhiên:

my %data; 
my @keys = qw(first second third); 

if (my @captured = $s =~ /abc (def) ghi (jkl) mno (pqr) /x) { 
    push @{ $data{$keys[$_]} }, $captured[$_] for 0 .. $#keys; 
} 

Hoặc, nếu tên của các biến thực sự là first, second vv, hoặc nếu tên của các bộ đệm không quan trọng nhưng chỉ để không, bạn có thể sử dụng :

my @data; 
if (my @captured = $s =~ /abc (def) ghi (jkl) mno (pqr) /x) { 
    push @{ $data[$_] }, $captured[$_] for 0 .. $#captured; 
} 
+0

Bạn chỉ đang cố gắng làm một bản sao sâu trong ví dụ đầu tiên đó? Tôi chỉ cần rút ra cái dế của Storable. Hoặc là, hoặc ví dụ của bạn cần một số vòng lặp để xây dựng các giá trị mà bạn lưu trữ trong '$ data'. :) –

+0

@brian Tôi đã nghĩ đến việc phân tích cú pháp một tệp trong đó mỗi dòng cung cấp cho bạn giá trị 'đầu tiên' và' giây' và 'thứ ba' và lưu trữ các giá trị đó trong các mảng của riêng chúng. So sánh với ví dụ của Leon Timmerman (http://stackoverflow.com/questions/2259784/how-can-i-store-captures-from-a-perl-regular-expression-into-separate-variables/2259795#2259795) –

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