Комментирование регулярных выражений

11

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

m0nhawk
источник
2
Есть, но вы должны быть более конкретными. Например, Bash поддерживает встроенные комментарии, а Python предлагает подробные регулярные выражения.
Сакиск
6
Мое эмпирическое правило для регулярных выражений: если вам нужно комментировать регулярное выражение, это слишком сложно.
zzzzBov
1
И всегда включайте эту ссылку: regexcrossword.com
Kieveli
Я не обязательно согласен с тем, что если вы должны это прокомментировать, это слишком сложно. Сложное регулярное выражение все еще может спасти вас тонны остроумного императивного кода. Используйте хорошее описательное имя переменной, чтобы назначить регулярное выражение. Если это все еще недостаточно ясно, используйте краткий комментарий, чтобы передать первоначальное намерение за регулярным выражением.
Крейг,

Ответы:

10

На мой взгляд, хорошей практикой является кратко излагать в комментариях общую идею регулярного выражения. Это избавит других разработчиков (или иногда вас самих) от необходимости вставлять регулярные выражения в такой синтаксический анализатор, как RegExr , только для того, чтобы понять, что он делает.

pleinolijf
источник
2
RegExr произойдет в любом случае, если только разработчик не является регулярным выражением. Но я согласен с предоставлением общего описания; это то, что я делаю с моими регулярными выражениями.
Роберт Харви
3
+1: что-нибудь более подробное в конечном итоге станет ускоренным курсом в регулярных выражениях в качестве комментария.
Мэтт
Этот ответ и комментарии @zzzzBov имеют смысл.
m0nhawk
1
Мало того, что это избавляет от утомительной проверки регулярного выражения, чтобы понять его, но и делает понятным намерение первоначального программиста, особенно учитывая очевидную возможность того, что исходный программист неправильно понял само регулярное выражение в первый раз. Сказав это, во многих случаях назначение регулярного выражения для хорошего имени переменной может иметь большое значение для обеспечения адекватного документирования намерений.
Крейг,
9

Это в некоторой степени зависит от языка, но в вопросе язык не указан.

Книга «Dive Into Python» предлагает реализовать комментарии с использованием подробных регулярных выражений :

Python позволяет вам делать это с помощью подробных регулярных выражений. Подробное регулярное выражение отличается от компактного регулярного выражения двумя способами:

  • Пробелы игнорируются. Пробелы, табуляции и возврат каретки не совпадают с пробелами, табуляцией и возвратом каретки. Они совсем не совпадают. (Если вы хотите сопоставить пробел в подробном регулярном выражении, вам нужно избежать его, поставив перед ним обратную косую черту.)
  • Комментарии игнорируются. Комментарий в подробном регулярном выражении аналогичен комментарию в коде Python: он начинается с #символа и продолжается до конца строки. В данном случае это комментарий внутри многострочной строки, а не внутри исходного кода, но он работает так же.

Пример:

>>> pattern = """
^                   # beginning of string
M{0,4}              # thousands - 0 to 4 M's
(CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
                    #            or 500-800 (D, followed by 0 to 3 C's)
(XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
                    #        or 50-80 (L, followed by 0 to 3 X's)
(IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
                    #        or 5-8 (V, followed by 0 to 3 I's)
$                   # end of string
"""
>>> re.search(pattern, 'M', re.VERBOSE)                1

Источник и дальнейшие подробности здесь

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

Rotem
источник
2
Вместо того, чтобы хранить шаблон в переменной, вы можете использовать его re.compileв том месте, где вы определяете свой шаблон, и сохранять только полученный объект. Таким образом, флаги компиляции шаблона (включая re.VERBOSE) не нужно отделять от самого шаблона.
Джон Варфоломей
Действительно полезный ответ, спасибо! Но как я могу сопоставить, #если я использую подробный флаг? Кстати: ссылки на источник, кажется, не работает.
winklerrr
Итак, это #может быть найдено буквально, когда внутри класса персонажа: [#](source: docs.python.org/3/library/re.html#re.X )
winklerrr
8

Как правило, я напишу регулярное выражение и не объясню отдельные части регулярного выражения, а скорее, какова его цель. Вот что, что и почему. Это немного похоже на вопрос "Как должны выглядеть мои комментарии?" на что можно сказать: « Не пиши, что делает код, напиши, почему код делает то, что делает »

// Strip the leading "?" and remove the query parameters "offset=<integer>" & "count=<integer> so we have a pattern of the request"          
var search = location.search.substring(1).replace(/offset=[0-9]+?&/g, "").replace(/count=[0-9]+?&/g, "");

Если вы не пытаетесь научить кого-либо о регулярных выражениях с помощью комментариев в коде, я не думаю, что объясню, что будет делать каждый отдельный фрагмент. Работая с другими программистами, вы можете смело предполагать, что кто-то будет знать что-то вроде глобальных регулярных выражений.


источник
3
Вы были бы удивлены ...
Мэтт
6

Я думаю, это действительно зависит от того, как вы соединяете регулярное выражение. Вообще говоря, я думаю, что было бы плохой идеей помещать комментарии внутри самой строки регулярного выражения (насколько я знаю, это невозможно в большинстве сценариев). Если вам действительно нужно комментировать определенные части регулярного выражения (вы пытаетесь кого-то научить?), То разбивайте каждый кусок на отдельные строки в своих строках и комментируйте каждую строку, используя обычный процесс комментирования для вашего языка программирования. В противном случае ответ Pleinolijf довольно хороший.

пример:

string myregex = "\s" // Match any whitespace once
+ "\n"  // Match one newline character
+ "[a-zA-Z]";  // Match any letter
Matt
источник
4

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

Например:

const string FloatingPointNumberPattern = @"[-+]?[0-9]*\.?[0-9]+";

Вы можете добавить комментарий над этой константой, чтобы дать ей описание, но обычно достаточно имени самой константы.

Бернард
источник
1
Еще одна вещь, которая мне нравится в этом ответе, состоит в том, что, если он используется более чем в одном месте, намерение также необходимо нести, не забывая комментировать его.
J Trana
3

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

В таких случаях может быть целесообразно задокументировать примеры вариантов. Расположение этой документации может варьироваться в зависимости от суммы (например, не обязательно в коде).

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

Например, если во время разработки вы скажете что-то вроде «О, я не знал, что X может принять эту форму», тогда стоит документировать это (и, возможно, ту часть регулярного выражения, которая обрабатывает этот вариант).

bstovall
источник
2

Комментарии должны добавлять полезную информацию, которая не очевидна из кода.

  1. Облегчите понимание того, что выражение должно делать на уровне требований, либо в самом коде, либо в комментарии. Какова цель этого выражения: проверить адреса электронной почты или выбрать канадские номера телефонов?
  2. Облегчите понимание того, что на самом деле делает выражение, то есть к чему оно относится. Сначала попытайтесь прояснить это, разбив выражение: если вы сначала проверите все дефисы, а затем удалите все числа, а затем сделаете из двухчастного выражения переменные, содержащие промежуточные значения, это будет намного легче читать, и читатель будет в состоянии шагать по вашей логике по одному шагу за раз. (Существует знаменитый ответ на вопрос о SE, где кто-то пытается расшифровать какой-то старый код, который включает в себя битовую манипуляцию «>>» и выясняет, установлены ли определенные флаги, где ответ раскрывает не только то, что код действительно делает, но и как автор вопроса должен пойти на деконструкцию такого рода кода в будущем, что я и пытаюсь описать, но могу »

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

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

Encaitar
источник
1

Извлеките RegEx в отдельный класс с осмысленным именем. Затем я документировал код с помощью автоматических тестов.

Это обеспечит

  • То, что код на самом деле работает - также для угловых случаев
  • Гарантирует, что быстрое "исправление" не испортит много угловых случаев
  • Может документировать оптимизации, когда обратный трекинг отключен

Естественно, ваш класс может содержать несколько регулярных выражений.

Карло В. Данго
источник