我在数据库中有一堆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>
直到在一个表格单元格中有超过1个PDF链接
默认情况下,regex引擎是贪婪的,它尽可能地消耗匹配。为了扭转这种行为,你可以使用懒惰量词,正如这篇文章所解释的:贪婪、不情愿、所有格量词。因此,您必须在量词之后添加额外的?
,以尝试使用尽可能少的量词进行匹配。要使贪心构造变懒,可以使用[^'s]+?
.
一些包含字符串
http://www.example.com/subfolder/name.pdf
or/subfolder/name.pdf
但是如何用另一个模式替换这个模式呢?
可以看到," http://www.example.com
"是可选的。您可以使用(?:group)
和?
量词使模式的一部分成为可选的。
带有可选组的模式:
(?:http://www'.example'.com)?/('S+?)'.pdf
- 不要忘记转义点,因为它们在正则表达式中有特殊的含义。
- 注意,我使用
'S
(大写"S")而不是[^'s]
(它们都完全相同)。
(?<!'w)
(前面没有单词字符)和'b
作为单词边界,以避免匹配作为另一个单词的一部分(正如我在您的问题中评论的那样)。
正则表达式:
(?<!'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);
测试regex101
这里有一个沙盒示例: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);