[英]How can I validate regex?
我想測試 PHP 中正則表達式的有效性,最好是在使用它之前。 執行此操作的唯一方法是實際嘗試preg_match()
並查看它是否返回FALSE
嗎?
是否有更簡單/正確的方法來測試有效的正則表達式?
// This is valid, both opening ( and closing )
var_dump(preg_match('~Valid(Regular)Expression~', '') === false);
// This is invalid, no opening ( for the closing )
var_dump(preg_match('~InvalidRegular)Expression~', '') === false);
正如用戶pozs所說,還可以考慮在測試環境中將@
放在 preg_match() ( @preg_match()
)前面,以防止出現警告或通知。
要驗證 RegExp,只需針對null
運行它(無需預先知道要測試的數據) 。 如果它返回顯式 false ( === false
),則它已損壞。 否則它是有效的,盡管它不需要匹配任何東西。
所以沒有必要編寫自己的 RegExp 驗證器。 真是浪費時間...
我創建了一個簡單的函數,可以調用它來檢查 preg
function is_preg_error()
{
$errors = array(
PREG_NO_ERROR => 'Code 0 : No errors',
PREG_INTERNAL_ERROR => 'Code 1 : There was an internal PCRE error',
PREG_BACKTRACK_LIMIT_ERROR => 'Code 2 : Backtrack limit was exhausted',
PREG_RECURSION_LIMIT_ERROR => 'Code 3 : Recursion limit was exhausted',
PREG_BAD_UTF8_ERROR => 'Code 4 : The offset didn\'t correspond to the begin of a valid UTF-8 code point',
PREG_BAD_UTF8_OFFSET_ERROR => 'Code 5 : Malformed UTF-8 data',
);
return $errors[preg_last_error()];
}
您可以使用以下代碼調用此函數:
preg_match('/(?:\D+|<\d+>)*[!?]/', 'foobar foobar foobar');
echo is_preg_error();
替代方案 - 正則表達式在線測試器
如果您想動態測試正則表達式preg_match(...) === false
似乎是您唯一的選擇。 PHP 沒有在使用正則表達式之前對其進行編譯的機制。
此外,您可能會發現preg_last_error是一個有用的功能。
另一方面,如果您有一個正則表達式並且只想在使用它之前知道它是否有效,那么那里有很多可用的工具。 我發現rubular.com使用起來很愉快。
如果您的引擎支持遞歸(PHP 應該),您可以使用正則表達式的噩夢來檢查它是否是語法正確的正則表達式。
但是,您無法通過算法判斷它是否會在不運行它的情況下給出您想要的結果。
/^((?:(?:[^?+*{}()[\]\\|]+|\\.|\[(?:\^?\\.|\^[^\\]|[^\\^])(?:[^\]\\]+|\\.)*\]|\((?:\?[:=!]|\?<[=!]|\?>)?(?1)??\)|\(\?(?:R|[+-]?\d+)\))(?:(?:[?+*]|\{\d+(?:,\d*)?\})[?+]?)?|\|)*)$/
如果不實際執行正則表達式,您將無法確定它是否有效。 我最近為 Zend 框架實現了一個類似的 RegexValidator。 工作得很好。
<?php
class Nuke_Validate_RegEx extends Zend_Validate_Abstract
{
/**
* Error constant
*/
const ERROR_INVALID_REGEX = 'invalidRegex';
/**
* Error messages
* @var array
*/
protected $_messageTemplates = array(
self::ERROR_INVALID_REGEX => "This is a regular expression PHP cannot parse.");
/**
* Runs the actual validation
* @param string $pattern The regular expression we are testing
* @return bool
*/
public function isValid($pattern)
{
if (@preg_match($pattern, "Lorem ipsum") === false) {
$this->_error(self::ERROR_INVALID_REGEX);
return false;
}
return true;
}
}
我不確定它是否支持 PCRE,但在https://chrome.google.com/webstore/detail/cmmblmkfaijaadfjapjddbeaoffeccib上有一個名為RegExp Tester的 Chrome 擴展。 我自己還沒有使用它,所以我不能保證它,但也許它可能有用?
我傾向於為您的正則表達式設置一些單元測試。 這樣,您不僅可以確保正則表達式確實有效,而且在匹配方面也有效。
我發現使用 TDD 是開發 regex 的一種有效方法,這意味着將來擴展它會被簡化,因為您已經擁有所有可用的測試用例。
這個問題的答案對設置單元測試有很好的回答。
所以總而言之,對於所有提出這個問題的人,您可以使用這樣的函數驗證 PHP 中的正則表達式。
如果模式匹配給定的主題,preg_match() 返回 1,如果不匹配,則返回 0,如果發生錯誤,則返回 FALSE。 - PHP 手冊
/**
* Return an error message if the regular expression is invalid
*
* @param string $regex string to validate
* @return string
*/
function invalidRegex($regex)
{
if(preg_match($regex, null) !== false)
{
return '';
}
$errors = array(
PREG_NO_ERROR => 'Code 0 : No errors',
PREG_INTERNAL_ERROR => 'Code 1 : There was an internal PCRE error',
PREG_BACKTRACK_LIMIT_ERROR => 'Code 2 : Backtrack limit was exhausted',
PREG_RECURSION_LIMIT_ERROR => 'Code 3 : Recursion limit was exhausted',
PREG_BAD_UTF8_ERROR => 'Code 4 : The offset didn\'t correspond to the begin of a valid UTF-8 code point',
PREG_BAD_UTF8_OFFSET_ERROR => 'Code 5 : Malformed UTF-8 data',
);
return $errors[preg_last_error()];
}
哪個可以這樣使用。
if($error = invalidRegex('/foo//'))
{
die($error);
}
您可以使用 T-Regx 中的valid()
pattern('InvalidRegular)Expression')->valid(); // bool (false)
只需使用簡單的方法 - 查看 preg_match 是否返回錯誤值:
//look is a regex or not
$look = "your_regex_string";
if (preg_match("/".$look."/", "test_string") !== false) {
//regex_valid
} else {
//regex_invalid
}
您應該嘗試將正則表達式與NULL
匹配。 如果結果為 FALSE ( === FALSE
),則存在錯誤。
在 PHP >= 5.5 中,您可以使用以下內容自動獲取內置錯誤消息,而無需定義自己的函數來獲取它:
// For PHP >= 8, use the built-in strEndsWith instead of this function.
// Taken from https://www.php.net/manual/en/function.str-ends-with.php#125967
function endsWith($haystack, $needle) {
$length = strlen($needle);
return $length > 0 ? substr($haystack, -$length) === $needle : true;
}
function test_regex($regex) {
preg_match($regex, NULL);
$constants = get_defined_constants(true)['pcre'];
foreach ($constants as $key => $value) {
if (!endsWith($key, '_ERROR')) {
unset($constants[$key]);
}
}
return array_flip($constants)[preg_last_error()];
}
請注意,對preg_match()
的調用仍會針對無效的正則表達式發出警告。 可以使用set_error_handler()
使用自定義錯誤處理程序捕獲警告。
請參閱我可以嘗試/捕獲警告嗎? .
根據PCRE 參考,在使用表達式之前,沒有這種方法可以測試表達式的有效性。 但我認為,如果有人使用無效的表達式,這是該應用程序中的設計錯誤,而不是運行時錯誤,所以你應該沒問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.