Как исправить это многострочное регулярное выражение в Ruby?
У меня есть регулярное выражение в Ruby, которое не работает должным образом в многострочном режиме.
Я пытаюсь преобразовать текст Markdown в разметку Textile-eque, используемую в Redmine. Проблема заключается в моем регулярном выражении для преобразования блоков кода. Он должен найти любые строки, ведущие с 4 пробелами или табуляцией, а затем обернуть их в тегиpre .markdownText = '# header
some text that precedes code
var foo = 9;
var fn = function() {}
fn();
some post text'
puts markdownText.gsub!(/(^(?:s{4}|t).*?$)+/m,"<pre>n\1n</pre>")
Предполагаемый результат:
# header
some text that precedes code
<pre>
var foo = 9;
var fn = function() {}
fn();
</pre>
some post text
Проблема заключается в том, что закрывающий тег pre печатается в конце документа вместо этого после " fn ();". Я попробовал некоторые варианты следующего выражения, но оно не соответствует:
gsub!(/(^(?:s{4}|t).*?$)+^(S)/m, "<pre>n\1n</pre>\2")
Как мне получить регулярное выражение, чтобы оно соответствовало только блоку кода с отступом? Вы можете проверить это регулярное выражение на Rubular здесь .
4 ответа:
Во-первых, обратите внимание, что
'm'
многострочный режим в Ruby эквивалентен's'
однострочному режиму других языков. Другими словами;'m'
режим в Ruby означает: "точка соответствует всем".Это регулярное выражение довольно хорошо справится с сопоставлением раздела кода типа markdown:
re = / # Match a MARKDOWN CODE section. (\r?\n) # $1: CODE must be preceded by blank line ( # $2: CODE contents (?: # Group for multiple lines of code. (?:\r?\n)+ # Each line preceded by a newline, (?:[ ]{4}|\t).* # and begins with four spaces or tab. )+ # One or more CODE lines \r?\n # CODE folowed by blank line. ) # End $2: CODE contents (?=\r?\n) # CODE folowed by blank line. /x result = subject.gsub(re, '\1<pre>\2</pre>')
Это требует наличия пустой строки до и после раздела кода и позволяет использовать пустые строки внутри самого раздела кода. Он допускает либо
\r\n
, либо\n
окончание строки. Обратите внимание, что это не раздевание первые 4 пробела (или табуляции) перед каждой строкой. Это потребует большей сложности кода. (Я не рубиновый парень, поэтому не могу помочь с этим.)Я бы рекомендовал посмотреть на сам источник markdown, чтобы увидеть, как это действительно делается.
/ ^(\s{4} / \t)+.+\;\n$ / m
Работает немного лучше, но все равно берет новую строку, которая нам не нужна. здесь это на rubular.
Это работает для меня с вашим вводом образца.
markdownText.gsub(/\n?((\s{4}.+)+)/, "\n<pre>#{$1}\n</pre>")
Здесь Еще один, который захватывает все отступы линий в одном блоке
((?:^(?: {4}|\t)[^\n]*$\n?)+)