Как убрать медлительность этого регулярного выражения? - PullRequest
0 голосов
/ 22 марта 2019

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

(\d+\s+[-]\s+.*?(?=\s+-)|\d+\s+[-].*)

Regex будет использовать этот текст

"Option 01 - Random phrase - Top Menu",
"Option 02 - Another Random Phrase - Su Menu",
"Option 03 - More 01 Phrase - Menu",
"Option 04 - More Phrase -",
"Option 05 - Simple Phrase"

Для того, чтобы оставаться таким

01 - Random phrase ",
02 - Another Random Phrase ",
03 - More 01 Phrase ",
04 - More Phrase ",
05 - Simple Phrase ",

Функция этого регулярного выражениячтобы получить номер с тире в начале, и идти до последнего тире.Пример:

  • dfhdjfhdjf 01 - текстовый текст - dkfdçsjf

Когда в конце нет никакого следа, в основном это происходит:

  • dfhdjfhdjf 01 - текстовый текст dkfdçsjf

Однако при отладке этого регулярного выражения на regex101.com обвиняется в наличииОт 63 до 122 шагов.То есть это регулярное выражение очень медленное.

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

Скажите, как я собираюсь решить медлительность этого регулярного выражения?

Ответы [ 3 ]

5 голосов
/ 22 марта 2019

Вам не следует слишком беспокоиться о шагах, которые вы видите на regex101.com, потому что библиотека C # regex очень надежна.Если вы протестируете простое регулярное выражение, например (?s)a.*?b в regex101, с очень длинной строкой, оно сообщит о катастрофическом возврате, в то время как в коде C # оно будет работать нормально.некоторая избыточность: см. повторяющийся шаблон \d+\s+[-].

Все, что вам нужно, это

\d+\s+-.*?(?=\s+-|$)

См. демонстрационный пример regex на regex101 и RegexStorm .

Если .*?(?=\s+-) должен совпадать только при наличии пробела после -, используйте

\d+\s+-(?:\s.*?(?=\s+-)|.+)

См. Еще демо 1 (меньше шагов :))/ demo 2 .

Если вы хотите еще больше оптимизировать его, вы можете изучить принцип unroll-the-loop *1029* , который ведет

\d+\s+-(?:\s+\S*(?:\s(?!\s*-)\S*)*|.+)

См. это демо регулярных выражений (наименьшее количество шагов).

Здесь \S*(?:\s(?!\s*-)\S*)* является эквивалентом (почти) .*?(?=\s+-|$), ноболее эффективен, так как фрагменты вплоть до пробела сопоставляются в «пакетах», проверки дефиса выполняются только при обнаружении пробела.

Подробности

  • \d+ - 1+ цифр
  • \s+ - 1+ пробелов
  • -- дефис
  • .*?(?=\s+-|$) - любые 0+ символов, как можно меньше, до первого появления 1+ пробелов и - или до конца строки.
  • (?:\s.*?(?=\s+-)|.+) - группа без захвата:
    • \s.*?(?=\s+-) - пробелы, 0+ символов как можно меньше, до 1+ пробелов и -
    • | -или
    • .+ - остаток строки.
  • \S*(?:\s(?!\s*-)\S*)*:
    • \S* - 0+ непробельных символов
    • (?:\s(?!\s*-)\S*)* - 0 или более повторений
      • \s - пробел
      • (?!\s*-) - без пробелов 0+ и -
      • \S* - 0+ непробельных символов
2 голосов
/ 22 марта 2019

Вы также можете попробовать \d+\s+-[^-]*, чтобы получить то, что вы хотите.На данный момент это самое низкое количество шагов.Или вы можете добавить \d+\s+-[^-]*(?=\s) на тот случай, если вам нужно его обрезать прямо перед -. демо

1 голос
/ 22 марта 2019

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

^[^\d]*\d+\s+-\s+.*?(?:\s+-\s+.*?)?$

С этой начальной точки вы можете добавить скобки вокруг частей, которые вы хотите захватить.Например:

^[^\d]*(\d+)\s+-\s+(.*?)(?:\s+-\s+(.*?))?$

Это будет захватывать номер опции и тексты между тире.Третий захват будет пуст для вариантов 04 и 05.

РЕДАКТИРОВАТЬ: Теперь, когда автор вопроса уточнил, какие подстроки должны быть захвачены, я думаю, это простое и понятное регулярное выражение подходит:

\d+[^-]*-[^-"]*

Захватывает номер опции, ищет первую черту, затем записывает все до следующей черты или цитаты:

<01 - Random phrase >
<02 - Another Random Phrase >
<03 - More 01 Phrase >
<04 - More Phrase >
<05 - Simple Phrase>

Обратите внимание, что здесь добавлены угловые скобкипоказать замыкающие пробелы.Это то, что вы хотели?

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