PHP正则表达式怎么用_PHP正则表达式使用与实例讲解

31次阅读

PHP正则表达式基于PCRE库,通过preg_match、preg_replace等函数实现字符串查找、替换和分割。其核心是模式匹配,使用元字符(如.、d、^、$)和修饰符(如i、m、s、u)构建规则,支持捕获组、非贪婪匹配及多字节处理。常见陷阱包括灾难性回溯、未转义特殊字符和忽略UTF-8编码问题,优化建议有避免嵌套量词、使用非捕获组(?:…)、锚定位置及预过滤数据,以提升性能与准确性。

PHP正则表达式怎么用_PHP正则表达式使用与实例讲解

PHP正则表达式的核心在于通过特定的模式匹配字符串,它提供了一系列以preg_开头的函数,如preg_match用于查找,preg_replace用于替换,让开发者能以强大且灵活的方式处理文本数据。这套机制基于PCRE(Perl Compatible Regular Expressions)库,所以语法上与Perl的正则表达式高度兼容,是处理复杂字符串逻辑的利器。

要说PHP正则表达式怎么用,其实就是围绕着几个核心函数展开。你得先写好一个“模式”(pattern),这模式就是一串描述你想要匹配的文本规则的字符串,然后把这个模式和你要处理的字符串作为参数传给preg_matchpreg_replace之类的函数。举个最简单的例子,如果你想检查一个字符串里有没有数字,你的模式可能是/d+/,然后用preg_match去匹配。我个人觉得,理解正则表达式最关键的就是理解这个“模式”的写法,它就像一种微型编程语言,用符号来表达复杂的文本结构。

PHP正则表达式的基石:常用函数与基础模式

说起PHP里用正则表达式,那几个preg_开头的函数是绕不开的。我刚开始接触的时候,觉得这些函数名有点绕,但用多了就发现它们功能明确,分工也很清晰。

preg_match(pattern, subject, [matches], [flags], [offset]):这个函数是用来执行一次匹配的。它会尝试在subject字符串中查找preg_match0。如果找到了,就返回1,没找到返回0。preg_match1参数是个数组,如果传入了,它会存储所有匹配到的内容,包括完整的匹配和捕获组的内容。这在我们需要提取特定信息的时候非常有用。

立即学习PHP免费学习笔记(深入)”;

preg_match2:跟preg_match类似,但它会找出所有非重叠的匹配项。preg_match1数组的结构会根据preg_match5参数有所不同,preg_match6会把每个完整匹配作为一个元素,里面再包含捕获组;而preg_match7则会把所有捕获组1的匹配放在一个数组,所有捕获组2的匹配放在另一个数组。我个人更喜欢用preg_match6,觉得逻辑上更直观。

preg_match9:这个函数用于替换匹配到的内容。它会在subject中查找preg_match0,然后把所有匹配到的部分替换成preg_replace2字符串。preg_replace2里可以使用反向引用(如preg_replace4、preg_replace5)来引用preg_match0中捕获组的内容,这让替换操作变得非常灵活。比如,把所有preg_replace7格式的日期改成preg_replace8。

preg_replace9:顾名思义,它是用来分割字符串的,但不是用固定的字符串作为分隔符,而是用正则表达式模式。这在需要根据多种复杂分隔符来拆分字符串时特别好用。

preg_match0:这个函数则有点像数组过滤。它会遍历preg_match1数组中的每个元素,只返回那些匹配preg_match0的元素。

理解了这些函数,剩下的就是模式本身了。一个模式通常用斜杠preg_match3包裹起来,比如preg_match4。斜杠后面可以跟一些修饰符,比如preg_match5表示不区分大小写匹配。

<?php $text = "Hello, world! My phone number is 123-456-7890.";  // 查找是否包含 "world" if (preg_match("/world/i", $text)) {     echo "文本中包含 'world' (不区分大小写).n"; }  // 提取电话号码 if (preg_match("/(d{3})-(d{3})-(d{4})/", $text, $matches)) {     echo "找到电话号码: " . $matches[0] . "n";     echo "区号: " . $matches[1] . "n"; }  // 替换 "Hello" 为 "Hi" $newText = preg_replace("/Hello/", "Hi", $text); echo "替换后的文本: " . $newText . "n";  // 分割字符串 $parts = preg_split("/[ ,!]+/", $text); // 以空格、逗号或感叹号分割 print_r($parts); ?>

上面的例子展示了几个基本操作,但正则表达式的威力远不止于此。

PHP正则表达式中常用的元字符和修饰符有哪些?

要真正玩转正则表达式,就得深入了解那些奇奇怪怪的符号,也就是所谓的元字符(Metacharacters)和修饰符(Modifiers)。这些东西刚开始看会觉得眼花缭乱,但它们是构建复杂匹配模式的基石。

元字符: 这些符号在正则表达式中有特殊含义,而不是它们字面上的字符。

  • preg_match6:匹配除换行符以外的任何单个字符。这是最常用的通配符,但有时候也容易过度匹配。
  • preg_match7:匹配任何数字字符(等价于preg_match8)。
  • preg_match9:匹配任何非数字字符(等价于preg_replace0)。
  • preg_replace1:匹配任何单词字符(字母、数字或下划线,等价于preg_replace2)。
  • preg_replace3:匹配任何非单词字符(等价于preg_replace4)。
  • preg_replace5:匹配任何空白字符(空格、制表符、换行符等)。
  • preg_replace6:匹配任何非空白字符。
  • preg_replace7:匹配字符串的开头。
  • preg_replace8:匹配字符串的结尾。
  • preg_replace9:匹配前一个字符零次或多次。比如/d+/0能匹配空字符串、/d+/1、/d+/2等等。
  • /d+/3:匹配前一个字符一次或多次。/d+/4至少匹配一个/d+/1。
  • /d+/6:匹配前一个字符零次或一次。同时它也可以用来使量词变成非贪婪模式(/d+/7、/d+/8、/d+/9)。
  • preg_match0:匹配前一个字符恰好n次。
  • preg_match1:匹配前一个字符至少n次。
  • preg_match2:匹配前一个字符至少n次,但不超过m次。
  • preg_match3:字符集。匹配方括号中的任何一个字符。比如preg_match4匹配任何一个小写元音字母。
  • preg_match5:否定字符集。匹配不在方括号中的任何一个字符。preg_replace0匹配任何非数字字符。
  • preg_match7:或。匹配管道符左右的任何一个模式。preg_match8匹配preg_match9或preg_0。
  • preg_1:捕获组。将括号内的模式作为一个整体进行匹配,并且可以捕获匹配到的内容。也可以用来改变操作符的优先级。
  • preg_2:转义字符。如果想匹配一个元字符本身,比如想匹配preg_match6而不是任何字符,你就得用preg_4。

修饰符(Flags): 这些是放在正则表达式模式末尾的单个字母,用来改变匹配行为。

  • preg_5 (PCRE_CASELESS):不区分大小写匹配。preg_6会匹配preg_7、preg_8、preg_9。
  • preg_match(pattern, subject, [matches], [flags], [offset])0 (PCRE_MULTILINE):多行模式。preg_replace7和preg_replace8会匹配每行的开头和结尾,而不仅仅是整个字符串的开头和结尾。
  • preg_match(pattern, subject, [matches], [flags], [offset])3 (PCRE_DOTALL):点号(preg_match6)匹配所有字符,包括换行符。如果没有preg_match(pattern, subject, [matches], [flags], [offset])3修饰符,preg_match6不匹配换行符。
  • preg_match(pattern, subject, [matches], [flags], [offset])7 (PCRE_UNGREEDY):非贪婪模式。默认情况下,量词(preg_replace9、/d+/3、/d+/6、subject1)是贪婪的,会尽可能多地匹配。preg_match(pattern, subject, [matches], [flags], [offset])7修饰符会让它们变成非贪婪,尽可能少地匹配。这在解析HTML/XML标签时特别有用,比如subject3。
  • subject4 (PCRE_UTF8):开启UTF-8模式。处理多字节字符(如中文)时非常重要,否则preg_replace1等可能会出现意想不到的结果。

我个人在使用时,preg_5、preg_match(pattern, subject, [matches], [flags], [offset])0、preg_match(pattern, subject, [matches], [flags], [offset])3、preg_match(pattern, subject, [matches], [flags], [offset])7、subject4这几个是最常用的。尤其是在处理用户输入或者解析网页内容时,对大小写、多行、换行符以及贪婪模式的控制,直接决定了匹配结果的准确性。忘记subject4修饰符处理中文时,那简直是噩梦。

如何在PHP中实现字符串的查找、替换和分割操作?

在PHP中,字符串的查找、替换和分割是正则表达式最常见的应用场景。虽然PHP提供了preg_match02、preg_match03、preg_match04这些函数来处理简单的字符串操作,但一旦涉及到模式匹配,preg_系列函数就显得不可替代了。

查找(Find):preg_matchpreg_match07是查找的主力。 如果你只需要知道一个字符串中是否存在某个模式,或者只需要获取第一次匹配到的内容,preg_match就够了。

<?php $html = "<p>这是一个<b>粗体</b>的文本。</p><p>这是另一个<b>粗体</b>。</p>";  // 查找第一个粗体标签内的内容 if (preg_match("/<b>(.*?)</b>/", $html, $matches)) {     echo "第一次匹配到的粗体内容: " . $matches[1] . "n"; // $matches[0]是完整匹配,[1]是第一个捕获组 } // 输出: 第一次匹配到的粗体内容: 粗体 ?>

如果需要找到所有匹配项,那preg_match07就是你的朋友。

<?php $html = "<p>这是一个<b>粗体</b>的文本。</p><p>这是另一个<b>粗体</b>。</p>";  // 查找所有粗体标签内的内容 preg_match_all("/<b>(.*?)</b>/", $html, $matches_all, PREG_SET_ORDER); foreach ($matches_all as $match) {     echo "找到粗体内容: " . $match[1] . "n"; } // 输出: // 找到粗体内容: 粗体 // 找到粗体内容: 粗体 ?>

这里preg_match6让preg_match11的每个元素都是一个完整的匹配数组,方便遍历。

替换(Replace):preg_replace是替换操作的核心。它不仅能替换固定字符串,还能根据模式动态替换,甚至利用反向引用重新组织字符串。

<?php $log_entry = "错误: 用户ID 12345 登录失败,IP地址 192.168.1.100。";  // 将IP地址替换为[隐藏IP] $sanitized_log = preg_replace("/d{1,3}.d{1,3}.d{1,3}.d{1,3}/", "[隐藏IP]", $log_entry); echo "替换IP后: " . $sanitized_log . "n"; // 输出: 替换IP后: 错误: 用户ID 12345 登录失败,IP地址 [隐藏IP]。  // 格式化日期,例如把 "2023-10-26" 替换成 "26/10/2023" $date_str = "今天是 2023-10-26,明天是 2023-10-27。"; $formatted_date_str = preg_replace("/(d{4})-(d{2})-(d{2})/", "$3/$2/$1", $date_str); echo "格式化日期后: " . $formatted_date_str . "n"; // 输出: 格式化日期后: 今天是 26/10/2023,明天是 27/10/2023。 ?>

在第二个例子中,preg_match13就是反向引用,它引用了模式中第三、第二和第一个捕获组的内容。这种能力是preg_match03无法比拟的。

PHP正则表达式怎么用_PHP正则表达式使用与实例讲解

达芬奇

达芬奇——你的AI创作大师

PHP正则表达式怎么用_PHP正则表达式使用与实例讲解50

查看详情 PHP正则表达式怎么用_PHP正则表达式使用与实例讲解

分割(Split):preg_match15允许你用复杂的模式来分割字符串,而不仅仅是单一的字符或字符串。

<?php $data_line = "姓名:张三;年龄:30,性别:男|城市:北京";  // 以分号、逗号或竖线作为分隔符分割 $parts = preg_split("/[;,|]+/", $data_line); print_r($parts); /* 输出: Array (     [0] => 姓名:张三     [1] => 年龄:30     [2] => 性别:男     [3] => 城市:北京 ) */  $sentence = "Hello   world!  How are you?"; // 以一个或多个空格、感叹号分割,并保留分隔符 $words_with_delimiters = preg_split("/(s+|!)/", $sentence, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); print_r($words_with_delimiters); /* 输出: Array (     [0] => Hello     [1] =>     [2] => world     [3] => !     [4] =>     [5] => How     [6] =>     [7] => are     [8] =>     [9] => you ) */ ?>

preg_match16这个标志位特别有意思,它能让分隔符本身也作为结果数组的一部分被捕获进来。preg_match17则会过滤掉空字符串。这种细粒度的控制在处理一些非标准格式数据时非常有用。

PHP正则表达式在使用时有哪些常见陷阱和性能优化建议?

正则表达式虽然强大,但它也是一把双刃剑。不恰当的使用不仅可能导致错误的结果,还可能引发严重的性能问题,甚至让你的服务器CPU飙升。我曾经就被一个看似简单的正则搞得焦头烂额,才意识到这些陷阱有多深。

常见陷阱:

  1. 灾难性回溯(Catastrophic Backtracking): 这是最致命的性能问题之一。当你的正则表达式包含嵌套的量词,并且这些量词可以匹配相同的内容时,就可能发生。例如,preg_match18匹配preg_match19,在匹配失败时(比如preg_match20),引擎会尝试所有可能的/d+/1组合,导致指数级的回溯。

    • 例子: preg_match22 匹配 preg_match20 就会很慢。
    • 避免: 尽量避免嵌套的、重复的量词,尤其是当它们能够匹配相同内容时。可以使用原子组preg_match24来防止回溯。
  2. 贪婪与非贪婪模式的误解: 默认情况下,量词(preg_replace9, /d+/3, preg_match2)是贪婪的,会尽可能多地匹配。但有时候你需要的是非贪婪匹配,比如解析HTML标签时,preg_match28会匹配从第一个preg_match29到最后一个preg_match30的所有内容,而不是单个标签。

    • 解决: 在量词后面加上/d+/6使其变为非贪婪,例如preg_match32。或者使用preg_match(pattern, subject, [matches], [flags], [offset])7修饰符使整个模式非贪婪。
  3. 忘记转义特殊字符: 如果你的模式中需要匹配preg_match6、preg_replace9、/d+/3、/d+/6、preg_match38、preg_match39、preg_match40、preg_match41、preg_match42、preg_match43、preg_replace7、preg_replace8、preg_match7、preg_2这些元字符本身,而不是它们的特殊含义,你必须用preg_2进行转义。

    • 例子: 匹配preg_match49,模式应该是preg_match50,而不是preg_match51。
  4. 编码问题(UTF-8): 在处理包含多字节字符(如中文)的字符串时,如果忘记添加subject4修饰符(PCRE_UTF8),preg_replace1、preg_replace5、preg_match6等元字符可能会产生错误的结果,或者匹配失败。

    • 解决: 始终在模式末尾加上subject4修饰符,例如preg_match57。
  5. 不检查错误: preg_系列函数在匹配失败或模式无效时,会返回preg_match59或0,并可能发出警告。但更重要的是,preg_match60函数可以提供更详细的错误信息,这对于调试非常关键。

    • 建议: 在调用preg_函数后,总要检查preg_match60,尤其是在开发阶段。

性能优化建议:

  1. 模式越简单越好: 复杂的模式意味着更多的回溯和计算。如果能用简单的字符串函数(preg_match02, preg_match03, preg_match04)解决,就不要用正则表达式。

  2. 避免不必要的捕获组: 捕获组preg_match66会增加处理开销,因为引擎需要存储匹配到的内容。如果只是想把一部分模式作为一个整体,但不需要捕获其内容,可以使用非捕获组preg_match67。

    • 例子: preg_match68 比 preg_match69 效率略高。
  3. 使用更具体的字符类: 尽可能使用preg_match7、preg_replace1、preg_replace5或具体的字符集preg_match73,而不是宽泛的preg_match6。preg_match6需要尝试匹配更多可能性,效率较低。

  4. 锚定模式: 如果你知道匹配必须发生在字符串的开头或结尾,使用preg_replace7和preg_replace8来锚定模式。这能让引擎更快地确定匹配位置,避免不必要的扫描。

  5. 减少回溯: 这是最难但最重要的优化点。除了避免灾难性回溯的模式外,还可以使用原子组preg_match24来阻止引擎在某些部分进行回溯。

  6. 预过滤: 对于大型字符串,如果正则表达式匹配的模式只占很小一部分,可以先用preg_match02或preg_match80快速检查是否存在可能匹配的子字符串。如果不存在,就完全不需要运行正则表达式。

<?php // 灾难性回溯示例 (不要在生产环境运行,可能导致PHP进程卡死) // $pattern = '/^(a+)+b$/'; // $subject = str_repeat('a', 25) . 'c'; // 故意让它匹配失败 // preg_match($pattern, $subject); // echo preg_last_error() . "n"; // 通常不会有错误,只是执行时间超长  // 避免灾难性回溯的一种方式:使用原子组 $pattern_optimized = '/^(?>a+)b$/'; $subject = str_repeat('a', 25) . 'c'; if (preg_match($pattern_optimized, $subject)) {     echo "匹配成功n"; } else {     echo "匹配失败 (优化后的模式)n"; // 匹配失败,但不会回溯很久 }  // 非捕获组示例 $text = "apple banana cherry"; preg_match_all("/(?:apple|banana)/", $text, $matches); print_r($matches); // 只需要匹配,不需要捕获组的额外开销  // UTF

以上就是PHPphp教程 php word html 正则表达式 编码 app 字节 编程语言 apple php正则表达式 yy php perl 正则表达式 html strpos count xml 字符串 input 性能优化

php教程 php word html 正则表达式 编码 app 字节 编程语言 apple php正则表达式 yy php perl 正则表达式 html strpos count xml 字符串 input 性能优化

text=ZqhQzanResources