PHP模式搜索和替换

时间:2015-09-16 17:11:48

标签: php regex wordpress replace

我在数据库中有一堆rawr内容。

一些包含字符串http://www.example.com/subfolder/name.pdf/subfolder/name.pdf

我需要在这些模式替换上将它们转换为/wp-content/uploads/old/subfolder/name.pdf,可以有多个级别的子文件夹! /subfolder1/subfolder2/subfolder3/file.pdf

我使用的模式是

/http[^\s]+pdf/
/href="\/[^\s]+pdf/

但是如何用另一种模式替换模式呢? (上面的例子^)

我有

search for /http:\/\/www.example.com(.*).pdf"/
replace with /wp-content/uploads/old$1.pdf"

search for /href="\/pdf(.*)\.pdf">/

这种方法很好,直到一个表格单元格中有超过1个pdf链接

例如

<a href="/pdf/subdir/name.pdf">clickhere</a><a href="/pdf/subdir/name.pdf">2nd PDF</a>

2 个答案:

答案 0 :(得分:1)

  

这种方法很好,直到一个表格单元格中有超过1个pdf链接

默认情况下,正则表达式引擎为greedy,并且消耗尽可能多的尝试匹配。为了扭转此行为,您可以使用延迟量词,如本文所述:Greedy vs. Reluctant vs. Possessive Quantifiers。所以你必须在量词之后添加一个额外的?来尝试匹配,尽可能少。要使您的贪婪构造变得懒惰,请使用[^\s]+?

  

一些包含字符串http://www.example.com/subfolder/name.pdf   或/subfolder/name.pdf

     
    

但是如何用另一种模式替换模式呢?

  

如您所见,“http://www.example.com”是可选的。您可以使用(?:group)?量词来选择模式的一部分。

带有可选组的模式:

(?:http://www\.example\.com)?/(\S+?)\.pdf
  • 不要忘记逃避点,因为它们在正则表达式中具有特殊含义。
  • 请注意,我使用\S(大写字母“S”)代替[^\s](它们完全相同)。


还有一件事,您可以考虑在模式中添加一些边界。我建议使用(?<!\w)(不以单词字符开头)和\b word boundary来避免匹配作为另一个单词的一部分(正如我在您的问题中所评论的那样)。

正则表达式:

(?<!\w)(?:http://www\.example\.com)?/(\S+?)\.pdf\b

代码:

$re = "@(?<!\\w)(?:http://www\\.example\\.com)?/(\\S+?)\\.pdf\\b@i"; 
$str = "some containing string http://www.example.com/subfolder/name.pdf
        or /subfolder/name.pdf
        <a href=\"/pdf/subdir/name.pdf\">clickhere</a>
        <a href=\"/pdf/subdir/name.pdf\">2nd PDF</a>"; 
$subst = "/wp-content/uploads/old/$1.pdf"; 

$result = preg_replace($re, $subst, $str);

Test in regex101

答案 1 :(得分:0)

此处的沙箱示例:http://sandbox.onlinephpfunctions.com/code/cc47b98d16981b786cf2d573751b6a09a9725b90

$array = [
     "https://test.com/url/subfolder/subfolder/file.pdf",
     "https://test.com/url/subfolder1/subfolder/file.pdf",
     "/url/subfolder3/subfolder3/files.xml",
     "/url/subfolder/subfolder/file.pdf"
];

function setwpUrl($urls, $prepend) {
    for($i = 0; $i < count($urls); $i++) {
        preg_match_all("/(https?:\/\/[a-zA-Z0-9\.\-]+)?(.*)/", $urls[$i], $out);
        $urls[$i] = $prepend . $out[2][0];
    }
    return $urls;
}

$newUrls = setwpUrl($array, "/wp-content/uploads/old");

var_dump($newUrls);