Как мне исправить это многострочное регулярное выражение в Ruby? - PullRequest
7 голосов
/ 19 апреля 2011

У меня есть регулярное выражение в Ruby, которое не работает должным образом в многострочном режиме.

Я пытаюсь преобразовать текст Markdown в текстовую разметку, используемую в Redmine. Проблема в моем регулярном выражении для преобразования блоков кода. Он должен найти любые строки, начинающиеся с 4 пробелов или табуляции, а затем обернуть их в теги pre .

<code>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\\1\n
")

Ожидаемый результат:

<code># header

some text that precedes code

<pre>
    var foo = 9;
    var fn = function() {}

    fn();
некоторый текст поста

Проблема в том, что закрывающий тег pre печатается в конце документа, а не после "fn ();". Я попробовал несколько вариантов следующего выражения, но оно не соответствует:

<code>gsub!(/(^(?:\s{4}|\t).*?$)+^(\S)/m, "<pre>\n\\1\n
\\ 2" )

Как заставить регулярное выражение соответствовать только блоку с отступом кода? Вы можете проверить это регулярное выражение на Rubular здесь .

Ответы [ 4 ]

12 голосов
/ 19 апреля 2011

Во-первых, обратите внимание, что 'm' многострочный режим в Ruby эквивалентен 's' однострочному режиму других языков.Другими словами;Режим 'm' в Ruby означает: «точка соответствует всем» .

Это регулярное выражение выполнит довольно хорошую работу по сопоставлению фрагмента кода, подобного уценке:

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\2
')

Для этого требуется пустая строка до и после раздела кода и допускаются пустые строки в самом разделе кода.Он допускает либо \r\n, либо \n окончания строки.Обратите внимание, что это не удаляет первые 4 пробела (или табуляцию) перед каждой строкой.Это потребует большей сложности кода.(Я не рубиновый парень, поэтому ничего не могу с этим поделать.)

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

0 голосов
/ 19 апреля 2011

Это работает для меня с вашим примером ввода.

<code>markdownText.gsub(/\n?((\s{4}.+)+)/, "\n<pre>#{$1}\n
")
0 голосов
/ 19 апреля 2011

Здесь - еще один, который захватывает все отступы в одном блоке

((?:^(?: {4}|\t)[^\n]*$\n?)+)
0 голосов
/ 19 апреля 2011

/ ^ (\ s {4} | \ т) + + \;. \ П $ / м

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...