Сопоставьте перекрывающиеся шаблоны с захватом, используя регулярное выражение MATLAB - PullRequest
3 голосов
/ 11 мая 2009

Я пытаюсь разобрать файл журнала, который выглядит следующим образом:

%%%% 09-May-2009 04:10:29
% Starting foo
this is stuff
to ignore
%%%% 09-May-2009 04:10:50
% Starting bar
more stuff
to ignore
%%%% 09-May-2009 04:11:29
...

Этот отрывок содержит два периода времени, которые я хотел бы извлечь: от первого разделителя до второго и от второго до третьего. Я хотел бы использовать регулярное выражение для извлечения времени начала и окончания каждого из этих интервалов. Это в основном работает:

p = '%{4} (?<start>.*?)\n% Starting (?<name>.*?)\n.*?%{4} (?<stop>.*?)\n';
times = regexp(c,p,'names');

Возвращение:

times = 

1x16 struct array with fields:
    start
    name
    stop

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

На других языках вы можете использовать операторы обхода (lookahead, lookbehind) для решения этой проблемы. Документация по регулярным выражениям объясняет, как они работают в MATLAB, но я не смог заставить их работать, все еще захватывая совпадения. То есть мне нужно не только иметь возможность сопоставлять каждый разделитель, но и извлекать часть этого совпадения (отметку времени).

Возможно ли это?

P.S. Я понимаю, что могу решить эту проблему, написав простой конечный автомат или сопоставив разделители и постобработку, если нет способа заставить это работать.

Обновление: Спасибо за идеи обходного пути, всем. Я слышал от разработчика, и в настоящее время нет способа сделать это с помощью механизма регулярных выражений в MATLAB.

Ответы [ 3 ]

2 голосов
/ 11 мая 2009

MATLAB, похоже, не может захватить символы как токен, не удаляя их из строки (или, я бы сказал, I не смог сделать это с помощью MATLAB REGEXP ). Однако, отметив, что время остановки для одного блока текста равно времени начала следующего, я смог зафиксировать только время начала и имена с помощью REGEXP, а затем выполнить простую обработку, чтобы получить время остановки из время начала. Я использовал следующий образец текста:

c =

%%%% 09-May-2009 04:10:29
% Starting foo
this is stuff
to ignore
%%%% 09-May-2009 04:10:50
% Starting bar
more stuff
to ignore
%%%% 09-May-2009 04:11:29
some more junk

... и применил следующее выражение:

p = '%{4} (?<start>[^\n]*)\n% Starting (?<name>[^\n]*)[^%]*|%{4} (?<start>[^\n]*).*';

Затем обработку можно выполнить с помощью следующего кода:

names = regexp(c,p,'names');
[names.stop] = deal(names(2:end).start,[]);
names = names(1:end-1);

... что дает нам эти результаты для приведенного выше образца текста:

>> names(1)

ans = 

    start: '09-May-2009 04:10:29'
     name: 'foo'
     stop: '09-May-2009 04:10:50'

>> names(2)

ans = 

    start: '09-May-2009 04:10:50'
     name: 'bar'
     stop: '09-May-2009 04:11:29'
1 голос
/ 13 мая 2009

Если вы выполняете много синтаксического анализа и выполняете такую ​​работу, вы можете рассмотреть возможность использования Perl из Matlab . Он дает вам доступ к мощному движку регулярных выражений Perl и может также облегчить решение многих других проблем.

0 голосов
/ 11 мая 2009

Все, что вам нужно сделать, это обернуть взгляд вокруг части регулярного выражения, соответствующей второй метке времени:

'%{4} (?<start>.*?)\n% Starting (?<name>.*?)\n.*?(?=%{4} (?<stop>.*?)\n)'

РЕДАКТИРОВАТЬ: Здесь без именованных групп:

'%{4} (.*?)\n% Starting (.*?)\n.*?(?=%{4} (.*?)\n)'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...