2015-01-15 3 views
1

я пытаюсь соответствовать следующим образом:Regex Non Жадный Matching через переводы строк

str = "---title: Some Title\ndate: 01/01/2012---\n\nSome other stuff---\n\n" 

И я хотел бы получить:

"title: Some Title\ndate: 01/01/2012" 

Таким образом, регулярное выражение я придумал был:

~r/---(.+)---(.+)/s 

Это, к сожалению, будучи жадности и соответствия:

"title: Some Title\ndate: 01/01/2012---\n\nSome other stuff" 

Я также попытался нежадным оператора и что тоже не получилось:

(~r/---(.+)---(.+)?.*/s 

Любые предложения будут очень полезны.

Благодаря

+0

Я удалил теги Perl и PCRE, так как они не являются германинами. –

+0

Я искал решение PCRE'ish, так как я использую Elixir, у которого есть регулярное выражение PCRE. Следовательно, теги. – user3118605

ответ

0

Более общее регулярное выражение:

(?:---)?(?<key>[a-z]+)\s*:\s*(?<value>(?!\\n).+?)(?:\\n|---|$) 

Он разбивает матч в ключ: значение.

DEMO

+1

Спасибо. Я искал универсальное решение, то есть не то, что ожидает названия и даты. Я хотел бы, чтобы это работало на что угодно между «--- (некоторые вещи здесь) ---'. – user3118605

2

Использование string.scan функции, как показано ниже.

> str = "---title: Some Title\ndate: 01/01/2012---\n\nSome other stuff---\n\n" 
> str.scan(/---([\s\S]+?)---/)[0][0] 
=> "title: Some Title\ndate: 01/01/2012" 

Вывод вышеуказанной функции сканирования представляет собой двумерный массив из-за существования группы захвата. [\s\S]+? Соответствует одному или нескольким пробельным или непространственным символам, не являющимся жадным. Обратите внимание, что этот шаблон также будет соответствовать разрыву строки (\n, \r).

0

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

s.split(/---\n*/) 
#=> ["", "title: Some Title\ndate: 01/01/2012", "Some other stuff"] 

str.split(/---\n*/)[1] 
#=> "title: Some Title\ndate: 01/01/2012" 
+0

Спасибо, я действительно искал решение для захвата матча. – user3118605

0

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

str.scan(/---title:\s+([^\n]+)\ndate:\s+(\d{2}\/\d{2}\/\d{4})/) 
    #=> [["Some Title", "01/01/2012"]] 
+0

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

+0

Спасибо, @Alan. Я починил это. Небольшая вещь, но удаление lookie также позволило мне изменить 'title: \ s' на' title: \ s + '. [Читатели: Я раньше имел '(? <= --- title: \ s)' - («нулевая ширина») «положительный lookbehind»]. –

0

Perl-способ сделать это:

#!/usr/bin/perl 
use Modern::Perl; 

my $str = "---title: Some Title\ndate: 01/01/2012---\n\nSome other stuff---\n\n"; 
$str =~ s/---(.+?)---.*?$/$1/s; 
say $str; 

Выход:

title: Some Title 
date: 01/01/2012 
+0

Так здорово! Я знал, что мне нужно использовать сочетание неживого оператора, а также некоторые сочетания новых линий. Мне было интересно, зачем нам второй «?»? перед «$»? Разве этого недостаточно? '~ r /---(.+?)---.*$/ s' Спасибо! – user3118605

+0

Кроме того, он должен ** не ** быть жадным? Не могу я просто сделать, 'regex = ~ r/--- ([^ - {3}] +) ---. * $/S'? – user3118605