Проверить, является ли строка регулярным выражением

Есть ли хороший способ тестирования, если строка является регулярным выражением или обычной строкой в ​​PHP?

В идеале я хочу написать функцию для запуска строки через, которая возвращает true или false.

Я посмотрел preg_last_error():

<?php
preg_match('/[a-z]/', 'test');
var_dump(preg_last_error());
preg_match('invalid regex', 'test');
var_dump(preg_last_error());
?>

Где, очевидно, первая ошибка не является, а вторая. Но preg_last_error() возвращает int 0 оба раза.

Любые идеи?

Ответы

Ответ 1

Единственный простой способ проверить правильность регулярного выражения в PHP - использовать его и проверить, не выдается ли предупреждение.

ini_set('track_errors', 'on');
$php_errormsg = '';
@preg_match('/[blah/', '');
if($php_errormsg) echo 'regex is invalid';

Однако использование произвольного пользовательского ввода в качестве регулярного выражения является плохой идеей. В процессоре PCRE раньше были дыры безопасности (переполнение буфера = > удаленное выполнение кода), и возможно было бы создать специально созданные длинные регулярные выражения, для которых требуется много компиляции/памяти для компиляции/выполнения.

Ответ 2

Самый простой способ проверить, является ли строка регулярным выражением:

if( preg_match("/^\/.+\/[a-z]*$/i",$regex))

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

Причина preg_last_error возвращает 0, потому что "недопустимое регулярное выражение" не является:

  • PREG_INTERNAL_ERROR (внутренняя ошибка)
  • PREG_BACKTRACK_LIMIT_ERROR (чрезмерное принудительное обратное отслеживание)
  • PREG_RECURSION_LIMIT_ERROR (чрезмерно рекурсивно)
  • PREG_BAD_UTF8_ERROR (плохо форматированный UTF-8)
  • PREG_BAD_UTF8_OFFSET_ERROR (смещение до середины символа UTF-8)

Ответ 3

Почему бы просто не использовать... другое регулярное выражение? Три линии, no @ kludges или что-то еще:

// Test this string
$str = "/^[A-Za-z ]+$/";

// Compare it to a regex pattern that simulates any regex
$regex = "/^\/[\s\S]+\/$/";

// Will it blend?
echo (preg_match($regex, $str) ? "TRUE" : "FALSE");

Или, в форме функции, еще более симпатично:

public static function isRegex($str0) {
    $regex = "/^\/[\s\S]+\/$/";
    return preg_match($regex, $str0);
}

Это не проверяет достоверность; но похоже, что вопрос Is there a good way of test if a string is a regex or normal string in PHP?, и он делает это.

Ответ 4

Вот хороший ответ:

fooobar.com/info/93863/...

if(@preg_match($yourPattern, null) === false){
    //pattern is broken
}else{
    //pattern is real
}