Форматирование кода - подход к смягчению нечитабельно большого регулярного выражения? - PullRequest
3 голосов
/ 18 июля 2011

Я использую длинное регулярное выражение, которое довольно трудно уловить, если вы не написали его в предыдущие 5 минут -

"/([^\s]+)\s*[^\[]+\[([^\]]+)\]\s*"([^\s]+)\s*([^\s]+)\s*([^"]+)"\s*([^\s]+)\s*([^\s]+)         \s*"([^"]+)"\s*"([^"]+)"/

Существует ли общепринятый способ форматирования длинных регулярных выражений в коде, обеспечивающий лучшую читаемость?

Я думал о том, чтобы поместить каждую группу захвата в отдельную строку, например,

          /([^\s]+)
\s*[^\[]+\[([^\]]+)
     \]\s*"([^\s]+)
        \s*([^\s]+)
         \s*([^"]+)
       "\s*([^\s]+)
        \s*([^\s]+)
        \s*"([^"]+)
       "\s*"([^"]+)"/

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

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

Ответы [ 3 ]

2 голосов
/ 18 июля 2011

Просто используйте флаг x (что означает игнорирование пробелов).

И тогда вы также можете оставлять комментарии. Смотрите пример:

          /([^\s]+) #Matches 1+ not whitespace.
\s*[^\[]+\[([^\]]+) #Matches 0+whitespace and an open bracket "["
     \]\s*"([^\s]+) #Matches a closing brack, space and and an open ", and some text
        \s*([^\s]+) #Matches
         \s*([^"]+)
       "\s*([^\s]+)
        \s*([^\s]+)
        \s*"([^"]+)
       "\s*"([^"]+)"/x =~ 'ss[s] "ss" " " dd dd "sdf" "  df"sdfasdf'        

print Regexp.last_match  #=> ss[s] "ss" " " dd dd "sdf" "  df"

См .: http://codepad.org/PDSxQUQf

1 голос
/ 15 июня 2012

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

Пример:

/([^\s]+)
\s*  [^\[]+   \[ ( [^\]]+) \]
\s*           "  ( [^\s]+)    \s*  ([^\s]+)  \s* ([^"]+) "
\s*              ( [^\s]+)    \s*  ([^\s]+)
\s*           "  ( [^"]+ ) "
\s*           "  ( [^"]+ ) "/

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

Также может быть полезно сделать это для выражений, которые вы унаследовали, потому что что-то действительно выскочит на вас. (Я понятия не имел, что вы соединяли кавычки или скобки, пока я не создал вышеупомянутый, например)

1 голос
/ 18 июля 2011

Вы можете использовать это:

class Regexp
    def +(re)
      Regexp.new self.source + re.source
    end
end

Чтобы включить оператор '+' для объединения выражений Regex:

           /([^\s]+)/ + # Comment
/\s*[^\[]+\[([^\]]+)/ + # Comment
     /\]\s*"([^\s]+)/ + # Comment
        /\s*([^\s]+)/ + # Comment
         /\s*([^"]+)/ + # Comment
       /"\s*([^\s]+)/ + # Comment
        /\s*([^\s]+)/ + # Comment
        /\s*"([^"]+)/ + # Comment
      /"\s*"([^"]+)"/   # Comment
...