Как извлечь комментарий регулярного выражения

У меня есть регулярное выражение, подобное этому

(?<!(\w/))$#Cannot end with a word and slash

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

\##value must be a hash

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

Ответ 1

Здесь a.NET приправленный Regex для частичного разбора .Net шаблонов вкуса, который должен быть довольно близок:

\A
(?>
    \\.         # Capture an escaped character
    |           # OR
    \[\^?       # a character class
        (?:\\.|[^\]])*    # which may also contain escaped characters
    \]
    |           # OR
    \(\?(?# inline comment!)\#      
        (?<Comment>[^)]*)
    \)
    |           # OR
    \#(?<Comment>.*$)   # a common comment!
    |           # OR
    [^\[\\#]    # capture any regular character - not # or [
)*
\z

К счастью, в .Net каждая группа захвата запоминает все свои захваты, а не только последние, поэтому мы можем найти все захваты группы Comment в одном анализе. Регулярное выражение в значительной степени анализирует регулярное выражение - но вряд ли полностью, оно просто анализирует достаточно, чтобы найти комментарии.
Вот как вы используете результат:

Match parsed = Regex.Match(pattern, pattern,
                           RegexOptions.IgnorePatternWhitespace | 
                           RegexOptions.Multiline);
if (parsed.Success)
{
    foreach (Capture capture in parsed.Groups["Comment"].Captures)
    {
        Console.WriteLine(capture.Value);
    }
} 

Рабочий пример: http://ideone.com/YP3yt

Последнее слово предостережения - это регулярное выражение предполагает, что весь шаблон находится в режиме IgnorePatternWhitespace. Когда он не установлен, все # сопоставляются буквально. Имейте в виду, что флаг может меняться несколько раз в одном шаблоне. В (?-x)#(?x)#comment, например, независимо от IgnorePatternWhitespace, первый # сопоставляется буквально, (?x) снова включает флаг IgnorePatternWhitespace, а второй # игнорируется.

Если вы хотите надежное решение, вы можете использовать парсер языка regex.
Вероятно, вы можете адаптировать исходный код .Net и извлечь парсер:

Ответ 2

Что-то вроде этого должно работать (если вы запускаете его отдельно в каждой строке регулярного выражения). Сам комментарий (если он существует) будет в третьей группе захвата.

/^((\\.)|[^\\\#])*\#(.*)/

(\\.) соответствует экранированному символу, [^\#] соответствует любым несимметричным несимвольным символам, вместе с квантором * они соответствуют всей строке перед комментарием. Затем остальная часть регулярного выражения обнаруживает маркер комментария и извлекает текст.

Ответ 3

Один из упущенных опций в синтаксическом анализе regex - это режим RightToLeft.

извлечь комментарий с конца.

Можно просто создать шаблон, если мы проложим путь от конца строки до начала. Например,

^          
  .+?            # Workable regex 
 (?<Comment>     # Comment group
   (?<!\\)       # Not a comment if escaped.
   \#            # Anchor for actual comment
   [^#]+         # The actual commented text to stop at #
 )?              # We may not have a comment 
$

Используйте приведенный выше шаблон в С# с этими параметрами RegexOptions.RightToLeft | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline

может существовать регулярное выражение с включенным регулярным выражением на хэшах

Эта строка (?<!\\) # Not a comment if escaped. обрабатывает эту ситуацию, говоря, что есть продолжение \, у нас нет комментария.