Как проверить актуальность регулярного выражения?

Допустим, у нас есть два регулярных выражения:

1234.*

а также

.*

Входные данные :

1234567

Очевидно, они оба совпадают, но 1234.* лучше, так как это более конкретно. т.е. более актуально. Существует ли стандартный способ проверки, который более актуален?

редактировать:

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

Пример с номерами телефонов:

Входные данные:

31882481337

У нас есть правило для каждого из следующих регулярных выражений:

31.*
.*

В этом сценарии я хотел бы использовать правило, связанное с 31.*, потому что оно более конкретно для данного ввода. Если бы я не использовал регулярные выражения, это было бы легко, потому что я мог бы использовать механизм оценки, чтобы проверить, насколько он соответствует, однако эти правила могут иметь более продвинутые регулярные выражения, такие как:

31[89].*

4 ответа

Решение

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

Expression      Relevance
31.*              1
.*              0

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

Я могу придумать два способа грубо оценить "актуальность".

  1. Произвольно измените входные данные и сравните, сколько модификаций приводит к сбою каждого выражения.

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

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

h.*|verylongtext|anotherverylongtext

hell.*|v.*

При сопоставлении слова "привет" второе выражение является "более релевантным", но первое содержит гораздо больше терминальных символов и может получить намного лучшее ранжирование по второму решению. Но для сопоставления "очень длинного текста" первое "более актуально". Это показывает, что "релевантность" сильно зависит от фактического ввода, и вам придется проанализировать фактический путь сопоставления - то, что неявно делается первым решением. Но случайное изменение входных данных является довольно сложной задачей, поскольку пространство возможных входных данных довольно велико. Я думаю, это тоже не очень хорошо работает.

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

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

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

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

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

Ваш хороший пример, возможно, вы хотите принять номера, начиная с 1234. 1234.* работает как шарм... но это не тот язык, который вы указали. `1234\d* более конкретен и соответствует вашему языку в точности так, как вы указали... таким образом, он более актуален.

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

Я не знаю, является ли "актуальность" реальной проблемой. Каждый из них релевантен, и каждый из них будет соответствовать "1234567", как вы предлагаете. Как вы также говорите, однако, один ("1234.*") является более конкретным. С помощью регулярных выражений специфичность велика (в таком простом случае, как этот), и иногда вы можете оттачивать его настолько, что понимаете, что он вам вообще не нужен (регулярное выражение). Правило № 1 регулярных выражений: не используйте их, если это не нужно. Например, чтобы соответствовать "1234567", я бы пошел с:

$source = '1234567';
if ( stripos( $source, '1234' ) === 0 ) {
  $foo = substr( $source, 4 );
  // $source began with '1234' and $foo holds the rest
} else {
  // it didn't begin with '1234'
}

Это пример PHP, но идея в том, что, поскольку вы так тщательно отточили свою принятую ценность, вам даже не нужен PCRE. "Релевантность" мало что скажет вам о регулярном выражении (как бы вы определили "релевантность" в этом контексте?), Однако я думаю, что специфичность - это более объективное измерение, и возможность вместо этого использовать строковые функции без регулярных выражений наверняка как черт быть очень измеримым (на самом деле, это логическое - есть ли регулярное выражение или нет?).

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

Другие вопросы по тегам