>  기사  >  웹 프론트엔드  >  PHP에서 정규식 사용의 효율성 탐욕, 비탐욕 및 역추적에 대한 자세한 설명(코드 포함)

PHP에서 정규식 사용의 효율성 탐욕, 비탐욕 및 역추적에 대한 자세한 설명(코드 포함)

php中世界最好的语言
php中世界最好的语言원래의
2018-03-30 10:51:551403검색

이번에는 PHP에서 일반 그리디, 비그리디, 백트래킹(코드 포함)을 사용할 때의 효율성에 대해 자세히 설명하겠습니다. 노트란 무엇이며 다음은 실제 전투 사례를 살펴보겠습니다. .

먼저 정규표현으로 탐욕에 대해 알아보고, 비탐욕이란 무엇인가요? 아니면 일치 우선순위 수량자는 무엇이고 우선순위 무시 수량자는 무엇입니까?

알겠습니다. 개념이 무엇인지 모르므로 예를 들어 보겠습니다.

한 학생이 그 사이의 내용을 필터링하고 싶어 정규 규칙과 절차를 이렇게 썼습니다.

$str = preg_replace('%<script>.+?</script>%i','',$str);//非贪婪

아무 문제가 없는 것처럼 보이지만 사실은 그렇지 않습니다.

$str = '<script<script>alert(document.cookie)</script>>alert(document.cookie)</script>';

인 경우 위 절차를 수행한 후에도 결과는

$str = '<script<script>alert(document.cookie)</script>>alert(document.cookie)</script>'; 
$str = preg_replace('%<script>.+?</script>%i','',$str);//非贪婪 
print_r($str); 
//$str 输出为 <script>alert(document.cookie)</script>

이며 여전히 원하는 효과를 얻을 수 없습니다. 위의 것은 탐욕이 아니며, 어떤 것은 게으름이라고도 합니다. 탐욕스럽지 않은 기호는 수량 메타 문자 뒤에 ?, 예를 들어 +?, *?, ??(더 특별합니다. 향후 블로그에 이에 대해 쓰겠습니다) 등이 있습니다. ?를 쓰지 않으면 욕심이 없다는 뜻입니다. 예를 들어

$str = '<script<script>alert(document.cookie)</script>>alert(document.cookie)</script>'; 
$str = preg_replace('%<script>.+</script>%i','',$str);//非贪婪 
print_r($str); 
//$str 输出为 

위는 탐욕스러운 것과 탐욕스럽지 않은 것의 차이점을 소개한 것입니다. 다음으로 탐욕과 비탐으로 인한 역행 문제에 대해 이야기해보겠습니다. 먼저 작은 예를 살펴보겠습니다.

정규 표현식은 w*(d+)이고, String은 cfc456n입니다. 그러면 이 정규 표현식과 일치하는 $1은 무엇입니까? ?

답이 456이라면 축하합니다. 결과는 456이 아니라 6입니다. 이유를 아시나요?

CFC4N에서는 일반 엔진이 cfc456n 문자열과 일치하기 위해 일반 w*(d+)를 사용할 때 먼저 w*를 사용하여 문자열 cfc456n과 일치합니다. 그런 다음 w*는 문자열 cfc456n의 모든 문자와 일치합니다. 나머지 문자열과 일치하도록 d+에 남겨두고 나머지는 사라지게 됩니다. 이때 w* 규칙은 d+가 일치하도록 문자를 마지못해 뱉어냅니다. 동시에 문자를 뱉어내기 전에 점을 기록합니다. . 이 지점은 역추적에 사용되는 지점이며 d+는 n과 일치합니다. 일치하지 않는 것으로 확인되면 w*에게 다시 역추적 지점을 기록하도록 요청합니다. 캐릭터를 내뱉습니다. 이때 w*의 일치 결과는 cfc45 뿐이고 6n이 다시 6과 일치합니다. 일치가 성공한 것으로 확인되면 일치가 성공했음을 엔진에 알리게 됩니다. 직접 표시됩니다. 따라서 (d+)의 결과는 456이 아니라 6입니다.

위 정규식을 w*?(d+)로 변경해도(여기서는 탐욕스럽지 않음에 유의) 문자열은 여전히 ​​cfc456n입니다. 그러면 이때 정규 매칭 $1은 무엇입니까? ?

학생 A가 답변했습니다. 결과는 456입니다.

그렇습니다. 맞습니다. 456입니다. CFC4N은 묻고 싶습니다. 왜 456인가요?

왜 456인지 설명하겠습니다

정규식에는 수량자가 먼저 일치한다는 규칙이 있으므로 w*?는 문자열 cfc456과 먼저 일치합니다. w*? 엔진은 w+ ?한 번에 하나의 문자열만 일치하는 표현식을 사용하고 다음 문자와 일치하도록 다음 d+에 제어권을 넘깁니다. 동시에 일치가 실패하고 다시 일치하는 경우 여기로 반환되는 지점이 기록됩니다. 이것이 역추적 지점이다. w 뒤에는 수량자 *가 따르므로 *는 0부터 무수한 횟수를 나타내므로 첫 번째는 0번입니다. 즉, w*?는 빈 공간과 일치하고 역추적 지점을 기록하고 첫 번째와 일치하도록 제어권을 d+, d+에 넘깁니다. cfc456n 문자 c 중 하나가 매칭에 실패하면 제어권이 w*?에 넘겨져 cfc456n의 c와 일치하게 됩니다. w*?는 탐욕스럽지 않기 때문에 c와 성공적으로 일치하므로 a 시간을 기록하고 역추적 지점을 기록한 다음 f와 일치하도록 d+에 제어권을 줍니다. 그런 다음 d+는 다시 f와 일치하지 못하고 w*?에 제어권을 부여한 다음 w*?는 c와 일치하고 역추적 지점을 기록합니다. 이번에는 w*?의 일치 결과가 cfc )이고 d+에 제어권을 주면 d+가 4와 일치하므로 일치가 성공합니다. 그러면 수량자가 +이므로 1에서 수없이 일치하므로 나중에 일치합니다. , 그리고 5와 일치하면 성공하고 다시 6과 일치합니다. 성공하면 일치 작업을 계속합니다. 다음 문자는 n이고 일치는 실패합니다. d+ 다음에는 정규식이 없기 때문에 전체 정규식이 일치한다고 선언하고 결과는 cfc456이며 그 중 첫 번째 결과 집합은 456입니다. 친애하는 동창 여러분, 지금 질문의 결과를 이해하셨습니까? 왜 456입니까?

네, 위의 예를 통해 탐욕 매칭과 비욕심 매칭의 원리를 이해하셨나요? 문자열을 처리하기 위해 Greedy 또는 Non-greedy를 사용해야 하는 경우를 이해하시나요?

Brother Niao의 기사에서는 표현식과 프로그램에 대해

$reg = "/<script>.*?<\/script>/is"; 
$str = "<script>********</script>"; //长度大于100014 
$ret = preg_repalce($reg, "", $str); //返回NULL

로 이야기합니다. 그 이유는 스택 공간이 소진되어 스택이 폭발할 때까지 역추적이 너무 많기 때문입니다.

再来看个例子。

字符串

$str = '<script>123456</script>';

正则表达式为

$strRegex1 = '%<script>.+<\/script>%'; 
$strRegex2 = '%<script>.+?<\/script>%'; 
$strRegex3 = '%<script>(?:(?!<\/script>).)+<\/script>%';

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

用正则匹配单个字符的详细解析

正则的位置匹配使用详解

위 내용은 PHP에서 정규식 사용의 효율성 탐욕, 비탐욕 및 역추적에 대한 자세한 설명(코드 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.