Как я могу выполнить многострочное сопоставление данных, полученных от алмазного оператора Perl - PullRequest
2 голосов
/ 22 декабря 2009

Есть ли какая-нибудь хитрость, чтобы сделать многострочные совпадения с регулярными выражениями с <> и зациклить их? Этот пример приводит к отсутствию совпадений при запуске файлов с \n в качестве разделителя новой строки:

while (<> =~ m/\n./) {
  print($.);
}

Мне нужно знать строку начала матча внутри цикла while, как в примере.

Цель состоит в том, чтобы найти все строки, содержащие менее 75 символов, за которыми следует строка, начинающаяся с пробела (стандартный способ разделения длинных строк на vCard):

while (<> =~ m/(^|\n).{0,74}\n /)

Ответы [ 3 ]

6 голосов
/ 22 декабря 2009

Что вы пытаетесь сделать в этом регулярном выражении? Похоже, вы пытаетесь найти любой случай, когда за новой строкой следует хотя бы один символ, после чего вы должны напечатать номер строки ($.) того, что соответствует этому критерию.

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

В любом случае см. Эту статью для ясного обсуждения многострочного соответствия: Regexp Power

Отредактировано после перехода к SO : Если вы действительно хотите найти строки длиной менее 75 символов и , следующую строку, начинающуюся с пробела, я бы не стал используйте одно регулярное выражение. Описание указывает на более простое и ясное (я думаю) решение: (1) отфильтровать все строки длиной менее 75 символов (функция length хороша для этого). Для оставшихся строк (2) проверьте, начинается ли следующая строка с пробела. Это дает вам ясную логику и простое регулярное выражение для написания.

В ответ на вопрос о получении «следующей» строки. Подумайте об этом наоборот: вы хотите проверять каждую следующую строку, но только если строка предыдущая была меньше 75 символов. Так как насчет этого:

my $prev = <>; # Initialize $prev with the first line

while (<>) {
    # Add 1 to 75 for newline or chomp it perhaps?
    if (length $prev < 76) {
        print "$.: $_" if $_ =~ m/^\s/;
    }
    $prev = $_;
}

(Обратите внимание, что я ничего не знаю о формате vCard и что \s шире, чем буквально «один пробел». Поэтому вам, возможно, придется скорректировать этот код, чтобы он лучше соответствовал вашей проблеме.)

5 голосов
/ 23 декабря 2009

Вы помните, чтобы перевести ручку в многострочный режим, задав $/ пустую строку или неопределенное значение?

Следующая программа делает то, что вы хотите:

#! /usr/bin/perl

use warnings;
use strict;

$/ = "";

*ARGV = *DATA;

while (<>) {
  while (/^(.{0,75}\n(^[ \t].{1,75}\n)*)/mg) {
    my $vcard = $1;

    $vcard =~ s/\r?\n[ \t]//g;

    print $vcard;
  }
}

__DATA__
DESCRIPTION:This is a long description that exists on a long line.
DESCRIPTION:This is a long description
  that exists on a long line.
DESCRIPTION:This is a long descrip
 tion that exists o
 n a long line.

Выход:

$ ./try
DESCRIPTION:This is a long description that exists on a long line.
DESCRIPTION:This is a long description that exists on a long line.
DESCRIPTION:This is a long description that exists on a long line.
3 голосов
/ 23 декабря 2009

У вас есть файл с произвольным текстом, смешанным с vCards?

Если все, что у вас есть, - это набор файлов vCard в файле, и вы хотите их проанализировать, то в CPAN .

есть несколько модулей парсинга vCard.

См., Например,

Text :: vCard , в частности Text :: vCard :: Addressbook .

Что касается,

while (<> =~ m/\n./) {
  print($.);
}

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

Если не должно быть более одной строки продолжения после каждой строки короче 76 символов, следующее может соответствовать требованиям:

#!/usr/bin/perl

use strict; use warnings;

for 
( 
    my $this = <>, my $next = <>;
    defined ($next = <>);
    close ARGV if eof
) 
{
    printf "%s : %d\n", $ARGV, $. - 1 if 76 > length $this and $next =~ /^ /;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...