[Perl]: чтение каталога и файлов и регулярное выражение - PullRequest
2 голосов
/ 12 мая 2009

из этой строки, (champs1 (champs6 donnee_o donnee_f) [(champs2 [] (champs3 _YOJNJeyyyyyyB (champs4 donnee_x)) (debut 144825 25345) (fin 244102 40647)), (champs2 [] (champs3 _FuGNJeyyyyyyB (champs4 donnee_z)) (debut 796443 190570) (fin 145247 42663))] [] [])., я хотел бы извлечь первое число после слова "дебют" и первое число после слова "плавник". Я пишу это:

while (my $readfile = <FILE>) #read each line and check the first value X1 after the word "coorDeb" and the first value X2 after the word "coorFin"
{
    my ($line) = $_;
    chomp ($line);

    ($first, $second)= ~m/coorDeb/\s\S*\s\S*\s\S*\s\S*\s\S*; #CoorDeb first, following by X1

    $X1=$first; $X4=$second;
    $lenght1=$second-$first; # Calculation of the lenght of first segment

    $line  =~ m//coorFin/(\s*)\S*\s*\S*\s*\S*\s*\S*\s*(\S*/); #CoorFin first, following by X1
    $lenght2=$second-$first; # Calculation of the lenght of first segment

    push(@elements1, $lenght1); #Push the lenght into a table to compute the mean of lenght for the segment n°1
    push(@elements2, $lenght2); #Push the lenght into a table to compute the mean of lenght for the segment n°2
}

Может кто-нибудь помочь мне с регулярным выражением, пожалуйста? Спасибо.

Ответы [ 2 ]

4 голосов
/ 12 мая 2009

Вы делаете этот способ слишком сложным, пытаясь посчитать поля и вычислить смещения в строке и так далее. Предполагая, что вы ищете подходящие пары дебют / плавник, вы можете использовать

#!/usr/bin/perl

use strict;
use warnings;

my @elements;
while (<DATA>) {
  my $line = $_;
  push @elements, $line =~ /debut (\d+).*?fin (\d+)/g;
}

print join ',', @elements;
print "\n";
__DATA__
(champs1 (champs6 donnee_o donnee_f) [(champs2 [] (champs3 _YOJNJeyyyyyyB (champs4 donnee_x)) (debut 144825 25345) (fin 244102 40647)), (champs2 [] (champs3 _FuGNJeyyyyyyB (champs4 donnee_z)) (debut 796443 190570) (fin 145247 42663))] [] [])

Этот код генерирует вывод

144825,244102,796443,145247

($line даже на самом деле не требуется, поскольку m// по умолчанию работает на $_, но я оставил это там на случай, если вам действительно потребуется выполнить другую обработку. немного более запутанный, чем я чувствую, уместно здесь.)

Если вас не интересуют совпадающие пары, вы также можете использовать два отдельных массива и заменить строку push на

push @debuts, $line =~ /debut (\d+)/g;
push @fins, $line =~ /fin (\d+)/g;
0 голосов
/ 12 мая 2009

Если я правильно понял, вам просто нужно прочитать файл и найти два значения. Эти значения представляют собой последовательность цифр после слова «фин» и после слова «дебют». Прямо сейчас вы пытаетесь сопоставить их, ища что-то, что происходит перед строкой, которая вас интересует. Возможно, вам следует искать актуальную информацию, представляющую интерес.

В регулярном выражении почти всегда лучше искать интересный текст, чем пытаться пропустить неинтересный текст. Что-то вроде следующего будет работать лучше.

Обратите внимание, что я изменил чтение вашего файла, потому что вы читали в переменную, а затем обрабатывали $ _, что (почти наверняка) не то, что вы имели в виду.

while (my $line = <FILE>) #read each line from FILE.
{
    chomp ($line);

    # These two lines could be combined but this is a little clearer.
    # Matching against [0-9] because \d matches all unicode digits.
    my ($fin_digits) = $line =~ /fin\s+([0-9]+)/;   
    my ($debut_digits) = $line =~ /debut\s+([0-9]+)/; # as above.

    # Continue processing below...
}

Теперь, одно отличие состоит в том, что данные вашего примера показывают множественные вхождения fin и debut в одну строку. Если это так, вам понадобится немного другое регулярное выражение. Дайте нам всем знать, так ли это на самом деле.

UPDATE

Учитывая, что у вас действительно совпадающие пары на одной и той же линии, вы можете использовать что-то вроде следующего. Опять же, я добавил только соответствие регулярных выражений, а не код обработки. Этот код фактически допускает произвольное количество пар в одной строке.

while (my $line = <FILE>) #read each line from FILE.
{
    chomp ($line);

    # These two lines could be combined but this is a little clearer.
    # Matching against [0-9] because \d matches all unicode digits.
    # In list context, m// returns the matches in order, the /g modifier
    # makes this a global match - in a loop this means each pair of
    # matches will be returned in order.
    while (my ($debut, $fin) =~ /debut\s+([0-9]+).+?fin\s+([0-9]+)/g)
    {
           # result processing here.
    }


}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...