首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在preg_replace或preg_replace_callback期间保存对数组的regex反向引用

如何在preg_replace或preg_replace_callback期间保存对数组的regex反向引用
EN

Stack Overflow用户
提问于 2013-08-30 21:11:41
回答 2查看 361关注 0票数 1

问题是:我有一个数据库,里面满是用XHTML标记的文章。我们的应用程序使用普林斯XML生成PDF。这方面的一个工件是使用以下模式将脚注内联地标记起来:

代码语言:javascript
运行
复制
<p>Some paragraph text<span class="fnt">This is the text of a footnote</span>.</p>

Prince用一个数字脚注标记替换每个span.fnt,并将所附文本呈现为页面底部的脚注。

我们希望以电子书格式呈现相同的内容,XHTML是一个很好的起点,但是内联脚注非常糟糕。我想要做的是将我的电子书构建脚本中的脚注转换为尾注。

我就是这么想的:

  1. 创建一个名为$endnotes的空数组来存储尾注文本。
  2. 将变量$endnote_no设置为零。此变量将保存当前的尾注编号,将内联显示为尾注标记,并用于将尾注标记链接到特定的尾注。
  3. 使用preg_replacepreg_replace_callback查找<span class="fnt">(.*?)</span>的每个实例。
  4. 为每个实例增加$endnote_no,并将内联span替换为'<sup><a href="#endnote_‘。$endnote_no。‘.$endnote_no’
  5. 将脚注文本推送到$endnotes数组,以便在文档末尾使用它。
  6. 在用数字尾注引用替换所有脚注之后,迭代$endnotes数组,在XHTML中将尾注作为有序列表显示出来。

这个过程有点超出了我对PHP的理解,当我试图将它转换成代码时,我会迷失方向。到目前为止,我主要根据PHP文档中的代码示例将这些内容拼凑在一起:

代码语言:javascript
运行
复制
$endnotes = array();
$endnote_no = 0;
class Endnoter {

  public function replace($subject) {
    $this->endnote_no = 0;
    return preg_replace_callback('`<span class="fnt">(.*?)</span>`', array($this, '_callback'), $subject);
  }

  public function _callback($matches) {
    array_push($endnotes, $1);
    return '<sup><a href="#endnote_' . $this->endnote_no++ . '">' . $this->endnote_no . '</a></sup>';
  }
}

..。

代码语言:javascript
运行
复制
$replacer = new Endnoter();
$replacer->replace($body);
echo '<pre>';
print_r($endnotes); // Just checking to see if the $endnotes are there.
echo '</pre>';

任何指导都是有帮助的,特别是如果有更简单的方法来达到这个目的的话。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-30 21:52:25

我不知道更简单的方法,但你已经走到一半了。这似乎很管用。

我只是稍微清理了一下,将变量移到类中,并添加了一个输出方法来获得脚注列表。

代码语言:javascript
运行
复制
class Endnoter
{
    private $number_of_notes = 0;
    private $footnote_texts = array();

    public function replace($input) {

        return preg_replace_callback('#<span class="fnt">(.*)</span>#i', array($this, 'replace_callback'), $input);

    }

    protected function replace_callback($matches) {

        // the text sits in the matches array
        // see http://php.net/manual/en/function.preg-replace-callback.php
        $this->footnote_texts[] = $matches[1];

        return '<sup><a href="#endnote_'.(++$this->number_of_notes).'">'.$this->number_of_notes.'</a></sup>';

    }

    public function getEndnotes() {
        $out = array();
        $out[] = '<ol>';

        foreach($this->footnote_texts as $text) {
            $out[] = '<li>'.$text.'</li>';
        }

        $out[] = '</ol>';

        return implode("\n", $out);
    }

 }
票数 2
EN

Stack Overflow用户

发布于 2013-08-30 21:43:11

首先,最好不要对HTML操作使用正则表达式;参见:如何在PHP中解析和处理HTML/XML?

但是,如果您真的想走这条路,那么您的代码有几处问题:

  1. 返回“”。$this->尾注_no。''; 例如,如果endnote_no为1,则会产生 “2”; 如果这些值都应该是相同的,那么首先要增加endnote_no: 返回“”。$this->尾注_no。''; 请注意调用前的++,而不是后。
  2. array_push($endnotes,1美元); $1不是一个定义的值。您正在寻找传入回调的数组,因此您需要$matches[1]
  3. print_r($endnotes); $endnotes不是在类之外定义的,所以您要么希望使用getter函数来检索$endnotes (通常更可取),要么在类中公开变量。带着吸气剂: 类$endnotes = $endnotes =数组();//用$this->尾注替换类中对$endnotes的任何引用,并添加一个函数:公共函数getEndnotes() {返回$this->endnote;}//然后在print_r外部($print_r->getEndnote());
  4. preg_replace_callback不是通过引用传递的,所以您实际上没有修改原始字符串。$replacer->replace($body);应该是$body = $replacer->replace($body);,除非您希望通过引用将主体传递到replace()函数并在那里更新其值。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18541524

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档