我在数据库中有一堆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>
答案 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);
答案 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);