php - preg_match_all 找不到所有匹配项
问题描述
我正在尝试查找包含域的字符串。我有以下模式:
"|s:\\d+:\\\\\"((?:.(?!s:\\d+))+?){$domain}(.+?)\\\\\";|"
这个(模式)似乎有效,但我只得到 PHP 中的前两个匹配项。
$filename = "caciki_tr.sql";
$domain = "caciki.com.tr";
$domain = escape($domain, ".");
$content = file_get_contents($filename);
$pattern = "|s:\\d+:\\\\\"((?:.(?!s:\\d+))+?){$domain}(.+?)\\\\\";|";
preg_match_all($pattern, $content, $matches, PREG_SET_ORDER);
print_r($matches);
function escape($string, $chars) {
$chars = str_split($chars);
foreach ($chars as $char) {
$string = str_replace($char, "\\{$char}", $string);
}
return $string;
}
Array
(
[0] => Array
(
[0] => s:121:\"/home/caciki/domains/caciki.com.tr/public_html/wp-content/themes/rafine/woocommerce/single-product/product-thumbnails.php\";
[1] => /home/caciki/domains/
[2] => /public_html/wp-content/themes/rafine/woocommerce/single-product/product-thumbnails.php
)
[1] => Array
(
[0] => s:81:\"/home/caciki/domains/caciki.com.tr/public_html/wp-content/themes/rafine/style.css\";
[1] => /home/caciki/domains/
[2] => /public_html/wp-content/themes/rafine/style.css
)
)
只有当我修改目标文件时,我才会得到所有匹配项 (11)。一定有什么东西破坏了模式/PHP。
我在 Python 和 C# 中测试了相同的模式,它们给出了正确的结果:
那么这里有什么问题呢?
caciki_tr.sql(目标文件)
更新:这里的模式与不同的子字符串一起使用(例如,域、url、用户名等)。并非目标文件中的所有字符串都遵循相同的模式。例如,URL 的模式应该能够匹配以下内容:
$url = "http://[DOMAIN_OMITTED]/~caciki";
$pattern = "|s:\d+:\\\\\"([^s]*(?:s(?!:\d)[^s]*)*){$url}(.+?)\\\\\";|";
s:28:\"http://[DOMAIN_OMITTED]/~caciki\";
s:28:\"<a href=\"http://[DOMAIN_OMITTED]/~caciki\">some page</a>\";
简而言之,在s:28:\"
和子字符串 ($url) 之间或子字符串之后可能没有字符串。所以它应该是可选的。
解决方案
当前的模式效率相当低,因为它包含一个损坏的“tempered greedy token(?:.(?!s:\d+))+?
” ,. 如果您想在生产中使用这样的正则表达式,这是一个非常低效的结构,应该“展开”。
您可以使用[^s]*(?:s(?!:\d)[^s]*)*
它来代替它:
"|s:\d+:\\\\\"([^s]*(?:s(?!:\d)[^s]*)*)$domain(.+?)\\\\\";|'
^^^^^^^^^^^^^^^^^^^^^^^
细节
[^s]*
- 0+ 以外的字符s
(?:
- 一个非捕获组重复...s(?!:\d)
-s
不跟:
+ 一个数字[^s]*
- 0+ 以外的字符s
)*
- 零次或多次。
请注意,如果您打算使用大文件,请确保您的模式尽可能高效。此外,如果您想处理大文件,这pcregrep
是一个有趣的解决方案(这是一个非常快速的工具)。
推荐阅读
- spring-boot - Spring cloud stream multi binder - Error KStreamBinderConfiguration required a single bean, but 2 were found
- hibernate - HTTP 状态 500 – Servlet [appServlet] 的内部服务器错误 Servlet.init() 引发异常
- mysql - 如何使用 Mysql 存储配置 Hangfire
- c# - 分发 Android 应用时,Visual Studio 2019 不再提供发布到 Google Play 的选项。解决方法是什么?
- pandas - 想要将每列中包含句子的一列数据框转换为字符串
- php - Laravel 6登录不适用于添加的用户
- css - 使用样式组件的媒体查询中的语法问题
- java - 如何获取 OffsetDateTime->LocalDateTime 并将其保存为 UTC?
- python - 如何使用多处理进行 1000 次模拟
- lynx - 如何在使用 Lynx 浏览器时验证人的身份