如何使用与 PHP str_replace 相同的字符串(字符)来打开和关闭标签?

How to use same string (character) with PHP str_replace to open and close tag?

我需要让我网站上的成员能够使用字符串 ` 输入代码并使用相同的字符串 ` 关闭它,就像我们在 Whosebug 中所做的那样。

这是我用过的代码

function replace_text($text) {
    $text = str_replace('`', '<code>', $text);
    $text = str_replace('`', '<\code>', $text);
    return $text;
}
add_filter('the_content', 'replace_text');

问题是只有第一个字符串 ` 被替换,然后 <code> 标签没有关闭。

您可以尝试使用 preg_replace 代替:

function replace_text($text) {
    return preg_replace('/`([^`]*)`/', '<code></code>', $text);
}

例如:

$text = 'some words and `some code` and some more words';
echo replace_text($text);

输出:

some words and <code>some code</code> and some more words

Demo on 3v4l.org

更新

如果您担心文本中存在转义反引号的可能性,您可以改用此正则表达式,它会使用负向后视检查第一个反引号是否未转义,然后忽略分隔符:

function replace_text($text) {
    return preg_replace('/(?<!\\)`((?:[^`\\]|\\.)*)`/', '<code></code>', $text);
}

另一个例子:

$text = 'some words \` and `some code` and `some \`more code` again';
echo replace_text($text);

输出:

some words \` and <code>some code</code> and <code>some \`more code</code> again

Demo on 3v4l.org

更新 2

为了也替换字符串中的任何 \`,我们在对 preg_match 的调用中添加第二对模式和替换:

function replace_text($text) {
    return preg_replace(array('/(?<!\\)`((?:[^`\\]|\\.)*)`/', '/\\`/'), array('<code></code>', '`'), $text);
}

$text = 'some words \` and `some code` and `some \`more code` again';
echo replace_text($text);

输出:

some words ` and <code>some code</code> and <code>some `more code</code> again

Demo on 3v4l.org

按照这些思路应该可以工作 - 它避免了正则表达式的性能开销(如果你关心这类事情)并且如果你有未关闭的块可以提供反馈:

while (strpos($text, '`')) {
    $firstOccurence = strpos($text, '`');
    $text = substr_replace($text, '<code>', $firstOccurence, 1);
    $secondOccurence = strpos($text, '`');
    if ($secondOccurence !== false) {
        $text = substr_replace($text, '</code>', $secondOccurence, 1);
    } else {
        throw new Exception('Unclosed block');
    }
}

此处示例:

https://repl.it/@abulafia/SparseLoathsomeExtensions

这将在找到刻度时继续解析文本。 str_pos 标识第一个刻度的位置,然后我们使用 substr_replace 替换它。然后我们重复这个过程,但是如果没有第二个刻度,抛出一个异常(或者做任何你想做的事!)

我会以一种尊重代码也可能包含一些反引号的可能性的方式来做。

为此,您可以使用带有捕获组和反向引用的正则表达式。第一个捕获组 (`+) 至少需要一个反引号,并且尽可能多地用于量词 +。然后在第 2 组中捕获以下所有字符。反向引用 </code>(使用转义反斜杠编码的字符串 <code>'\1')需要与第 1 组中捕获的一样多的反引号。

$s = 'Some ``code containing the backtick ` character`` should `work` as well.';

$tagged = preg_replace('~(`+)(.*?)\1~us', '<code></code>', $s);

结果:

Some <code>code containing the backtick ` character</code> should <code>work</code> as well.

但是,我建议使用完整的 markdown 解析器,可以在网上找到作为开源库。