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


Есть ли хороший способ проверить, является ли строка регулярным выражением или обычной строкой в 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 оба раза.

Есть идеи?

Author: Hosh Sadiq, 2012-05-28

4 answers

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

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

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

 7
Author: ThiefMaster, 2012-05-28 00:59:53

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

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)
 12
Author: Niet the Dark Absol, 2014-07-17 06:35:07

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

// 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?, и это действительно так.

 10
Author: Ben, 2013-04-19 05:52:55

Вот хороший ответ, как это сделать:

Https://stackoverflow.com/a/12941133/2519073

if(@preg_match($yourPattern, null) === false){
    //pattern is broken
}else{
    //pattern is real
}
 8
Author: ya_dimon, 2017-05-23 12:02:11