Использование регулярных выражений для поиска всего кода, обозначенного 4 пробелами - PullRequest
0 голосов
/ 17 января 2012

Учитывая текстовую область, аналогичную StackOverflow, я хотел бы обернуть код (с отступом 4 пробела) в блок pre / code. Я пытаюсь использовать следующее регулярное выражение, чтобы найти код:

<code>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
')

Но это не работает, вот пример в Rubular:

http://rubular.com/r/l5faSjR8ya

Любые предложения о том, как сделать это Regex, соответствовать коду, позволяют мне обернуть теги pre / code вокруг кода? Спасибо

Ответы [ 4 ]

2 голосов
/ 18 января 2012

Я думаю, что есть выход из режима кода с любым завершающим переводом строки, за которым не следует ни табуляция, ни 4 пробела. Не уверен, но последующие символы новой строки не будут включены в блок кода.

Я не слишком хорошо понимаю параметры регулярных выражений в Ruby, но, похоже, это работает: http://rubular.com/r/BlbreoO3sn

((?:^(?:[ ]{4}|\t).*$(?:\r?\n|\z))+) Теоретически, это в многострочном режиме.

Просто сделайте замену \1

EDIT
@Rachela Meadows - После дальнейшего изучения это довольно сложное регулярное выражение.
Мне удалось точно продублировать функциональные возможности блока <pre><code> онлайн-редактора здесь, на SO.

После получения каждого блока и перед переносом в <pre><code> все объекты разметки должны быть преобразованы (т. Е. Как < в &lt; и т. Д.) При этом я не делал этот шаг в примере кода Ruby ниже. У меня есть регулярные выражения для этого.

Специальное примечание об обрезке: основное регулярное выражение, приведенное ниже, не включает в себя остаточные завершающие символы новой строки. Так же как и функциональность SO. Таким образом, блок кода является правильным сверху вниз.
Однако первые 4 пробела (или табуляция), которые могут содержать в теле, не могут быть обрезаны (и они должны быть) в главном регулярном выражении. Для этого нужен обратный звонок.

Игра с режимом gsub block , легко обрезать ведущие пробелы / табуляцию.

Дайте мне знать, если у вас есть какие-либо проблемы с этим.

Ссылки -
Рубул (для регулярных выражений): http://rubular.com/r/pp9oRLQ0xo
Ideone (для рабочего кода Ruby): http://ideone.com/aA9it

Regex сжатый -
(^\s*$\n|\A)(^(?:[ ]{4}|\t).*[^\s].*$\n?(?:(?:^\s*$\n?)*^(?:[ ]{4}|\t).*[^\s].*$\n?)*)

Regex расширен -

(^\s*$\n|\A)                                # Capt grp 1, block is preceeded by a blank line or begin of string
(                                           # Begin "Capture group 2", start of pre/code block
   ^(?:[ ]{4}|\t) .* [^\s] .* $ \n?            # First line of code block (note - lines must contain at least 1 non-whitespace character)
   (?:                                         # Start "Optionally, get more lines of code"
       (?: ^ \s* $ \n? )*                         # Many optional blank lines
       ^(?:[ ]{4}|\t) .* [^\s] .* $ \n?           # Another line of code 
   )*                                          # End "Optionally, get more lines of code", do 0 or more times
)                                           # End "Capture group 2", end of pre/code block

Рубиновый код -


regex = /(^\s*$\n|\A)(^(?:[ ]{4}|\t).*[^\s].*$\n?(?:(?:^\s*$\n?)*^(?:[ ]{4}|\t).*[^\s].*$\n?)*)/;

data = '
Hello Worldsasdasdffasdfasdf  asdf

    thisdqweee

    asdfasdfasdfasdf
sdfg

    #YYYY {
    height: 100%;
    min-height: 800px;
    margin-right: 20px;
    position: relative;
    }


    #ZZZZZZ {
    height: 100%;
    overflow: hidden;
    }';


# ---
result = data.gsub(regex) {
   ||
   x=$2;
     ## Construct the return value '\1<pre&gt<code&gt\2</code&gt</pre&gt'.
     ## But, trim each line with 1 to 4 leading spaces (or a tab with regex on the bottom).
     ## They are not necessary now, they are replaced with a code block.

   $1 + '<pre&gt<code&gt' +   x.gsub(/^[ ]{1,4}/, '') + '</code&gt</pre&gt'
};

# Note - Tabs can be trimed too, use : x.gsub(/^(?:[ ]{1,4}|\t)/,'') in the above

print result;
1 голос
/ 17 января 2012

Я думаю, что для вашего паттерна в начале требуются две новые линии.

Может быть, так?((?:(?:[ ]{4}|\t).*(?:\r?\n|$))+)?
$ используется для сопоставления, если последняя строка имеет отступ и не имеет новой строки)

http://rubular.com/r/Vg9HnJpjbw

Ruby:

<code>s = "before\n    indent1\n    indent2\nmiddle\n     indent1\nafter"
p s.gsub(/((?:(?:[ ]{4}|\t).*(?:\r?\n|$))+)/x, '<pre>\1
')

Выход:

<code>"before\n<pre>    indent1\n    indent2\n
в середине \ n
indent1\n
после "
1 голос
/ 17 января 2012

Если вы ищете совпадение с полными строками, явно не сопоставляйте (?:\r?\n)+, используйте ^ и $. Попробуйте

(\r?\n)((?:(?:^[ ]{4}|\t).*$)+)(?=\r?\n)
0 голосов
/ 18 января 2012

Я думаю, что один из ваших снимков новой строки является избыточным. Вы можете использовать ^ и $ с выключенным флагом s, чтобы соответствовать EOL, а не EOL, это лучший шаблон, чем попытка сопоставить символы новой строки.

Попробуйте этот шаблон:

/(?:^(?:[ ]{4}|\t).*$[\n\r]*)+/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...