2010-02-08 3 views
3

Я делаю простой синтаксический анализатор Textile и пытаюсь написать регулярное выражение для «blockquote», но мне трудно сопоставить несколько новых строк. Пример:Регулярное выражение для соответствия блоку текста с первой двойной новой строкой?

 
bq. first line of quote 
second line of quote 
third line of quote 

not part of the quote 

Он будет заменен BLOCKQUOTE тегов через preg_replace() поэтому в основном он должен соответствовать все между "bq." и первой двойной новой линией он попадается. Лучшее, что я могу сделать, это получить первую строку цитаты. Спасибо

+0

Под «простым» вы подразумеваете, что поддерживаете очень небольшое подмножество разметки Textile? Если нет, я предлагаю вам пересмотреть использование 'preg_replace()'; вы скоро обнаружите, что это затрудняет работу, а не меньше. Вероятно, вам лучше не использовать регулярные выражения. –

+0

Да, это всего лишь небольшая часть разметки, которую я поддерживаю. Из интереса, как бы вы это сделали, не используя регулярные выражения? Думали ли вы использовать их в какой-то момент (даже если используете preg_match), чтобы узнать, какая разметка используется? – Fourjays

ответ

6

Попробуйте это регулярное выражение:

(?s)bq\.((?!(\r?\n){2}).)*+ 

Значение:

(?s)   # enable dot-all option 
b    # match the character 'b' 
q    # match the character 'q' 
\.    # match the character '.' 
(    # start capture group 1 
    (?!   # start negative look ahead 
    (   #  start capture group 2 
     \r?  #  match the character '\r' and match it once or none at all 
     \n  #  match the character '\n' 
    ){2}  #  end capture group 2 and repeat it exactly 2 times 
)   # end negative look ahead 
    .   # match any character 
)*+   # end capture group 1 and repeat it zero or more times, possessively 

\r?\n соответствует Windows, * NIX и (новые) MacOS разрывы строк. Если вам нужно учитывать реальные старые компьютеры Mac, добавьте один \r к нему: \r?\n|\r

+1

Я бы, вероятно, использовал '{2}' вместо '{2,}', потому что вы не можете сказать, желательно ли есть все соседние строки. Это, конечно же, не является частью этого требования. – Tomalak

+0

+1, очень приятно. Почему притяжательный квантификатор, если ничего не следует за группой захвата? –

+0

@ Томалак: согласовано. Исправлена. –

0

Будет ли это работать?

'/(.+)\n\n/s' 

Я считаю, что это единственная линия.

+0

's' обычно называется« dot-all »(поскольку он также позволяет разбить строку'. '). Но выполнение того, что вы предлагаете, приведет к тому, что регулярное выражение будет соответствовать всему тексту, а затем вернется в строку, чтобы найти последний '\ n \ n'. Из строки 'ABC \ n \ nDEF \ n \ nGHIJ \ n \ nKLM' она будет соответствовать' ABC \ n \ nDEF \ n \ nGHIJ \ n \ n'. Не то, что Fourjays ищет ИМО. –

+0

Это правда. Должен был сделать + не голодный, я думаю .. Спасибо. – ziya

0

Мои инстинкты говорят мне что-то вроде ...

preg_match("/^bq\. (.+?)\n\n/s", $input, $matches) 

Так же, как говорит выше парень, то s флаг после / в конце RegEx означает, что . будет соответствовать символы новой строки. Обычно, без этого, RegEx являются своего рода одной строкой.

Тогда знак вопроса ? после .+ обозначает нежеланный матч, так что .+ не будет соответствовать, как он может; вместо этого он будет соответствовать минимально возможному, так что \n\n будет соответствовать первой доступной двойной линии.

В какой мере вы планируете поддерживать функции Textile? Потому что ваш RegEx может быть довольно сложным, так как Textile позволяет такие вещи, как ...

bq.. This is a block quote 

This is still a block quote 

или ...

bq(funky). This is a block quote belonging to the class funky! 

bq{color:red;}. Block quote with red text! 

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

+0

Я поддерживаю только то, что я считаю «наиболее распространенными» чертами (жирным, курсивом, зачеркиванием, цитатами, заголовками, параграфами, пулями). Я бы использовал только классы по абзацу. Пока регулярное выражение хорошо работает для вещей, подобных смелым, но я подозреваю, что мне придется сделать что-то более активное для маркированного списка. – Fourjays

+0

... и вложенный жирный/курсив? Я думаю, что '* это не будет работать с RegEx *' –

+0

Вложенный полужирный/курсив, похоже, работает нормально. Используя регулярное выражение, он выполняет прямую замену содержимого жирного «тега», поэтому курсивы остаются нетронутыми. – Fourjays

0

Редактировать: Ehr, неверный вопрос .. "bq." был значительным.

echo preg_replace('/^bq\.(.+?)\n\n/s', '<blockquote>$1</blockquote>', $str, 1); 

Иногда данные, которые вводятся с помощью WebForms содержит \ п вместо г \ просто \ п, которое сделало бы его

echo preg_replace('/^bq\.(.+?)\r\n\r\n/s', '<blockquote>$1</blockquote>', $str, 1); 

Questionmark позволяет добавить закрытие блоков цитат после первого двойного возвращения найденного («не жадный», я считаю, что это называется), поэтому любые другие двойные возвращения остаются в силе (если это не то, что вы хотите, выведите его явно).

1

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

$text =~ /(?s)bq\.(.+?)\n\n/g 
Смежные вопросы