Почему это регулярное выражение совпадает? - PullRequest
1 голос
/ 15 июля 2010

У меня есть это регулярное выражение:

(?<!Sub ).*\(.*\)

И я бы хотел, чтобы это соответствовало:

MsgBox ("Общее время выполнения для исправления полей AREA и TD:" & = imeElapsed & "minutes.")

Но не это:

Sub ChangeAreaTD ()

Но почему-то я все еще сопоставляю тот, который начинается с Sub ... Кто-нибудь знает, почему? Я думал, что исключу "Sub", выполнив

(?<!Sub )

Любая помощь приветствуется!

Спасибо.

Ответы [ 4 ]

3 голосов
/ 15 июля 2010

Сделайте это:

^MsgBox .*\(.*\)

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

Однако добавление символа ^ в начале регулярного выражения гарантирует начало строки. Затем измените Sub на MsgBox, чтобы оно совпадало только со строками, которые начинаются с MsgBox

2 голосов
/ 15 июля 2010

Ваше регулярное выражение (?<!Sub ).*\(.*\), в разобранном виде:

(?<!         # negative look-behind
  Sub        #   the string "Sub " must not occur before the current position
)            # end negative look-behind
.*           # anything       ~ matches up to the end of the string!
\(           # a literal "("  ~ causes the regex to backtrack to the last "("
  .*         # anything       ~ matches up to the end of the string again!
\)           # a literal ")"  ~ causes the regex to backtrack to the last ")"

Итак, с вашей тестовой строкой:

Sub ChangeAreaTD()
  • Просмотр выполнен немедленно (прямо в позиции 0).
  • .* после этого перемещается к концу строки.
  • Из-за этого .*, просмотр в действительности никогда не имеет значения.

Вы, вероятно, думали о

(?<!Sub .*)\(.*\)

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

Так что я бы сделал это (так какпрогнозирование переменной длины широко поддерживается):

^(?!.*\bSub\b)[^(]+\(([^)]+)\)

, что переводится как:

^           # At the start of the string,
(?!         # do a negative look-ahead:
  .*        #   anything
  \b        #   a word boundary
  Sub       #   the string "Sub"
  \b        #   another word bounday
)           # end negative look-ahead. If not found,
[^(]+       # match anything except an opening paren  ~ to prevent backtracking
\(          # match a literal "("
(           # match group 1
  [^)]+     #   match anything up to a closing paren  ~ to prevent backtracking
)           # end match group 1
\)          # match a literal ")".

, а затем перейти к содержимому группы совпадений 1.

Однако , регулярное выражение вообще ужасно плохо подходит для анализа кода.Это верно для HTML так же, как и для кода VB.Вы получите неправильные совпадения даже с улучшенным регулярным выражением.Например, здесь, из-за вложенных паренов:

MsgBox ("The total run time to fix all fields (AREA, TD)  is: ...")
1 голос
/ 15 июля 2010

У вас есть проблема с возвратом. Первые .* в (?<!Sub ).*\(.*\) могут соответствовать ChangeAreaTD или hangeAreaTD. В последнем случае предыдущими 4 символами являются ub C, что не соответствует Sub. Поскольку взгляд сзади отрицается, это считается совпадением!

Простое добавление ^ в начало вашего регулярного выражения не поможет вам, так как оглядывающийся назад - это фраза соответствия нулевой длины. ^(?<!MsgBox ) будет искать строку, которая следует за строкой, заканчивающейся на MsgBox. Вместо этого вам нужно ^(?!Sub )(.*\(.*\)). Это может быть интерпретировано как «Начиная с начала строки, убедитесь, что она не начинается с Sub. Затем, захватите все в строке, если это похоже на вызов метода».

Хорошее объяснение того, как движки regex анализируют внешний вид, можно найти здесь .

0 голосов
/ 15 июля 2010

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

(?<!Sub )[a-zA-Z][a-zA-Z0-9_]* *\(.*\)

Идентификатору может потребоваться больше токенов в зависимости от языка, с которым вы подходите.

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