Perl Regex - множественное сопоставление с образцом, необязательное сопоставление - PullRequest
2 голосов
/ 11 декабря 2010

Я застрял на этом регулярном выражении.Это соответствует 2 из моих 3 имен файлов.Нужна помощь в получении всех трех, если это возможно.Я также хочу извлечь одно из этих значений abc|def|ghi, а также ucsb|tech имя локали до расширения .edu | .net в переменные.

Хотел бы сделать это за один проход, если это возможно.Спасибо.

/home/test/abc/.last_run_dir
/home/test/def/.last_file_sent.mail@wolverine.ucsb.edu
/home/test/ghi/.last_file_sent.dp3.tech.net

Первая строка не набирается:

/home/test/abc/.last_run_dir

Регулярное выражение:

$line =~ m#home/test/(\w{3}).*[.](\w+)[.].*#

Код:

my $file = 'Index.lst';
open my $FILE, '<', $file or die "unable to open '$file' for reading: $!";
while (my $line = <$FILE>) {
    chomp($line);
    if ($line =~ m#home/test/(\w{3}).*[.](\w+)[.].*#) {
        open my $file2, '<', $line or die "unable to open '$file' for reading: $!";
        while(my $line2 = <$file2>) {
        print "$line2";
        }
        close $file2;
    }
} #end while
close $FILE;

Кроме того, как распечатать мои возможные совпадения?Если они необязательны?

Ответы [ 3 ]

4 голосов
/ 11 декабря 2010

Вы можете сделать что-то вроде:

#!/usr/bin/perl
use strict;
use warnings;

while(my $line=<DATA>) {
    chomp($line);
    if ($line =~ m#home/test/(\w{3})/\.(\w+)(?:.*\.(\w+)\.[^.]+)?|$#) {
        print "$line\n";
        print "1=$1\t2=$2\t3=$3\n";
    }
}

__DATA__
/home/test/abc/.last_run_dir
/home/test/def/.last_file_sent.mail@wolverine.ucsb.edu
/home/test/ghi/.last_file_sent.dp3.tech.net

Ouput:

/home/test/abc/.last_run_dir
1=abc   2=last_run_dir  3=
/home/test/def/.last_file_sent.mail@wolverine.ucsb.edu
1=def   2=last_file_sent    3=ucsb
/home/test/ghi/.last_file_sent.dp3.tech.net
1=ghi   2=last_file_sent    3=tech
3 голосов
/ 11 декабря 2010

Часть вашего регулярного выражения после w {3} заставляет искать следующую точку-слово-точку:

[.](\w+)[.].*

Простое исправление - сделать это необязательным,Но когда вы это сделаете, вам, вероятно, придется сначала заблокировать это. *: Указать, что это может быть любая строка символов, но не точка.(Хорошая практика в целом, кстати.)

$line =~ m#home/test/(\w{3})[^.]*([.](\w+)[.].*)?#

РЕДАКТИРОВАТЬ: я вижу, что мое решение может потребоваться немного тестирования для проверки периодов в нужных местах, к вашему сведению

0 голосов
/ 11 декабря 2010

Ваше регулярное выражение требует два экземпляра "."чтобы соответствовать.Если второй является необязательным, используйте [.]?

$line =~ m#home/test/(\w{3}).*[.](\w+)[.]?.*#;
...