【问题标题】:preg_replace_callback() memory issuepreg_replace_callback() 内存问题
【发布时间】:2009-03-31 14:15:06
【问题描述】:

我在测试查找/替换功能时遇到了内存问题。

假设搜索主题是:

$subject = "

我在 A+ 杂志上写了一篇文章。 它很长,充满了文字。 我想用链接替换本文中的每个 A+ 实例 到 A+ 专用页面。

";

要找到的字符串:

$查找='A+'; $find = preg_quote($find,'/');

替换函数回调:

函数replaceCallback($match) { if (is_array($match)) { return ''。 stripslashes($match[0]) 。 ''; } }

和电话:

$result = preg_replace_callback($find, 'replaceCallback', $subject);

现在,从数据库中提取了完整的搜索模式。到目前为止,它是:

$find = '/(?![^<]+>)\b(voice recognition|test project reference|test|synesthesia|Superflux 2007|Suhjung Hur|scripts|Salvino a. Salvaggio|Professional Lighting Design Magazine|PLDChina|Nicolas Schöffer|Naziha Mestaoui|Nabi Art Center|Markos Novak|Mapping|Manuel Abendroth|liquid architecture|LAb[au] laboratory for Architecture and Urbanism|l'Arca Edizioni|l' ARCA n° 176 _ December 2002|Jérôme Decock|imagineering|hypertext|hypermedia|Game of Life|galerie Roger Tator|eversion|El Lissitzky|Bernhard Tschumi|Alexandre Plennevaux|A+)\b/s';

然后在 7 个 mysql 表的 23 列中查找(如果找到则替换)这个 $find 模式。

使用建议的 preg_replace() 而不是 preg_replace_callback() 似乎已经解决了内存问题,但我遇到了新问题:preg_replace() 返回的主题缺少很多内容...

更新:

内容丢失是由于使用 preg_quote($find,'/'); 它现在可以工作了,除了... 'A+' 在这个过程之后变成了 'A '。

【问题讨论】:

  • 您的实际搜索字符串是否更复杂?因为对于这个例子,你不需要 preg 任何东西 - str_replace() 会工作
  • 是的。事实上,我正在为很多潜在的“标签”调用这个函数。这就是为什么我必须让它变得无故障_现在是失败的。
  • 你的 php.ini 设置的内存限制是多少?
  • 我尝试增加它 ini_set('memory_limit','50M');仍然有问题在我必须找到的标签列表中,我有法语特殊字符,例如“ê,é”。会不会是问题?
  • 您能否更好地了解您的样本量?上面的精简示例实际上损害了我们现在为您提供帮助的能力。

标签: php regex preg-replace preg-replace-callback


【解决方案1】:

我正在尝试重现您的错误,但需要先修复一个解析错误。要么这些代码不足以成为一个好的示例,要么确实存在错误。

首先,您存储在 $find 中的值不是拉模式 - 所以我必须添加模式分隔符。

其次,您的替换字符串不包括锚标记的结束元素。

$subject = "
I wrote an article in the A+ magazine. It'\s very long and full of words. I want to replace every A+ instance in this text by a link to a page dedicated to A+.
";

$find='A+';
$find = preg_quote($find,'/');

function replaceCallback($match)
{
  if (is_array($match)) {
      return '<a class="tag" rel="tag-definition" title="Click to know more about ' .stripslashes($match[0]) . '" href="?tag=' . $match[0]. '">' . stripslashes($match[0])  . '</a>';
  }
}

$result = preg_replace_callback( "/$find/", 'replaceCallback', $subject);

echo $result;

此代码有效,但我不确定它是否是您想要的。另外,我强烈怀疑您根本不需要 preg_replace_callback()。

【讨论】:

  • 你能详细说明你的 las 声明吗?我真的不擅长正则表达式,所以非常感谢您的帮助。谢谢!
  • 使用 preg_replace_callback() 代替 preg_replace() 或 preg_replace_all() 的唯一原因是如果您需要在替换之前对匹配值执行其他语句(例如 htmlspecialchars())。跨度>
【解决方案2】:

这对我有用,我不得不稍微更改预赛匹配,但它会将我的每个 A+ 变成一个链接。最后,您还缺少&lt;/a&gt;

$subject = "I wrote an article in the A+ magazine. It'\s very long and full of words. I want to replace every A+ instance in this text by a link to a page dedicated to A+.";

function replaceCallback($match)
{
    if (is_array($match)) 
    {
        return '<a class="tag" rel="tag-definition" title="Click to know more about ' .stripslashes($match[0]) . '" href="?tag=' . $match[0]. '">' . stripslashes($match[0])  . '</a>';
    }
}

$result = preg_replace_callback("/A\+/", "replaceCallback", $subject);

echo $result;

【讨论】:

    【解决方案3】:

    好的 - 现在我知道你为什么要使用回调了

    首先,我会把你的回调改成这个

    function replaceCallback( $match )
    {
        if ( is_array( $match ) )
        {
            $htmlVersion    = htmlspecialchars( $match[1], ENT_COMPAT, 'UTF-8' );
            $urlVersion     = urlencode( $match[1] );
            return '<a class="tag" rel="tag-definition" title="Click to know more about ' . $htmlVersion . '" href="?tag=' . $urlVersion. '">' . $htmlVersion  . '</a>';
        }
        return $match;
    }
    

    stripslashes 命令对你没有任何好处。

    就解决内存问题而言,您可能希望将模式分解为多个模式并在循环中执行它们。我认为你的匹配对于 PHP 来说太大/太复杂了,无法在单个调用周期中处理它。

    【讨论】:

    • 根据您的建议,现在一切似乎都运行良好,除了我无法让“A+”显示为“A+”,它显示为“A”。但我可以看到它正确地位于数据库中,所以我猜这个问题超出了这一点。谢谢!
    • 哎呀,我说得太快了:replaceCallback 函数删除了 + 号。嗯。
    猜你喜欢
    • 2013-01-02
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 2010-12-26
    • 1970-01-01
    • 2015-04-19
    • 2010-09-22
    • 2014-12-19
    相关资源
    最近更新 更多