如果主题以引号开头,如何不执行preg_replace


How to not perform preg_replace if subject starts with quote

我正在尝试使用preg_replace将纯链接转换为HTML链接。然而,它正在替换已经转换的链接。

为了解决这个问题,如果链接以引号开头,我希望它忽略替换。

我认为可能需要积极的展望,但我所尝试的一切都没有奏效。

$string = '<a href="http://www.example.com">test</a> http://www.example.com';
$string = preg_replace("/((https?:'/'/['w]+[^ ','"'n'r't<]*))/is", "<a href='"$1'">$1</a>", $string);
var_dump($string);

上述输出:

<a href="<a href="http://www.example.com">http://www.example.com</a>">test</a> <a href="http://www.example.com">http://www.example.com</a>

何时输出:

<a href="http://www.example.com">test</a> <a href="http://www.example.com">http://www.example.com</a>

您可能会使用查找。Lookaround是零宽度断言,确保匹配/不匹配所讨论字符串周围的任何内容。它们不消耗任何字符
也就是说,在您的情况下,消极的后备可能是您需要的:

(?<![">])'bhttps?://'S+'b

PHP中,这将是:

<?php
$string = 'I want to be transformed to a proper link: http://www.google.com ';
$string .=  'But please leave me alone ';
$string .= '(<a href="https://www.google.com">https://www.google.com</a>).';
$regex = '~                # delimiter
              (?<![">])    # a neg. lookbehind
              https?://'S+ # http:// or https:// followed by not a whitespace
              'b           # a word boundary
          ~x';             # verbose to enable this explanation.
$string = preg_replace($regex, "<a href='$0'>$0</a>", $string);
echo $string;
?>

请参阅ideone.com上的演示。不过,也许解析器更合适。

由于您可以在preg_replace中使用Arrays,因此使用起来可能很方便,具体取决于您想要实现的目标:

        <?php
        $string = '<a href="http://www.example.com">test</a>    http://www.example.com';
        $rx     = array("&(<a.+https?:'/'/['w]+[^ ','"'n'r't<]*>)(.*)(<'/a'>)&si", "&('s){1,}(https?:'/'/['w]+[^ ','"'n'r't<]*)&");
        $rp     = array("$1$2$3", "<a href='"$2'">$2</a>");
        $string = preg_replace($rx,$rp, $string);
        var_dump($string);
        // DUMPS:
        // '<a href="http://www.example.com">test</a><a href="http://www.example.com">http://www.example.com</a>'

创意

您可以在已经存在的锚点处拆分字符串,并且只解析其间的部分。

守则

$input = '<a href="http://www.example.com">test</a> http://www.example.com';
// Split the string at existing anchors
// PREG_SPLIT_DELIM_CAPTURE flag includes the delimiters in the results set
$parts = preg_split('/(<a.*?>.*?<'/a>)/is', $input, PREG_SPLIT_DELIM_CAPTURE);
// Use array_map to parse each piece, and then join all pieces together
$output = join(array_map(function ($key, $part) {
    // Because we return the delimiter in the results set,
    // every $part with an uneven key is an anchor.
    return $key % 2
        ? preg_replace("/((https?:'/'/['w]+[^ ','"'n'r't<]*))/is", "<a href='"$1'">$1</a>", $part)
        : $part;
}, array_keys($parts), $parts);