我正在寻找一种从字符串中获取有效网址的方法:
$string = 'http://somesite.com/directory//sites/9/my_forms/3-895a3e/somefilename.jpg|:||:||:||:|19845';
我原来的解决方案是:
preg_match('#^[^:|]*#', str_replace('//', '/', $string), $modifiedPath);
但显然它会从http://中删除斜杠而不是字符串中间的斜杠。
我想要的原始输出是:
http://somesite.com/directory/sites/9/my_forms/3-895a3e/somefilename.jpg
我总是可以先断开字符串的http部分,但如果可能的话,希望以正则表达式形式提供更优雅的解决方案。感谢。
答案 0 :(得分:3)
这将完全符合您的要求:
<?php
$string = 'http://somesite.com/directory//sites/9/my_forms/3-895a3e/somefilename.jpg|:||:||:||:|19845';
preg_match('/^([^|]+)/', $string, $m); // get everything up to and NOT including the first pipe (|)
$string = $m[1];
$string = preg_replace('/(?<!:)\/\//', '/' ,$string); // replace all occurrences of // as long as they are not preceded by :
echo $string; // outputs: http://somesite.com/directory/sites/9/my_forms/3-895a3e/somefilename.jpg
exit;
?>
修改强>
正则表达式中的 (?<!X)
是所谓的lookbehind的语法。 X被我们正在测试的字符替换。
以下表达式将匹配双斜杠(/)的每个实例:
\/\/
但是我们需要确保我们正在寻找的匹配前面没有:字符,所以我们需要'lookbehind'我们的匹配以查看:字符是否存在。如果是,那么我们不希望它被算作匹配:
(?<!:)\/\/
!是什么说不匹配我们的lookbehind。如果我们将其更改为(?=:)\/\/
,那么它只会匹配在它们之前具有:的双斜杠。
这是一个快速教程,可以比lookahead and lookbehind tutorial
更好地解释它答案 1 :(得分:2)
假设你所有的字符串都是给定的形式,你不需要任何但最简单的正则表达式来做到这一点;如果你想要一个优雅的解决方案,那么正则表达式肯定不是你需要的。此外,双斜线在URL中是合法的,就像在Unix路径中一样,并且意味着单个斜杠的作用相同,因此您根本不需要完全删除它们。
为什么不
$url = array_shift(preg_split('/\|/', $string));
如果您真的非常关心删除URL中的双斜线,那么您可以按照
进行操作$url = preg_replace('/([^:])\/\//', '$1/', $url);
甚至将它们组合成
$url = preg_replace('/([^:])\/\//', '$1/', array_shift(preg_split('/\|/', $string)));
虽然最后一种形式有点毛茸茸。
答案 2 :(得分:0)
由于这是一个非常严格定义的情况,我认为只有一个preg是最优雅的解决方案。
从头到尾:
$sanitizedURL = preg_replace('~((?<!:)/(?=/)|\\|.+)~', '', $rawURL);
基本上,它的作用是查找任何前面的斜杠,它不是以冒号(:)开头,而后面跟着bij另一个正斜杠。它还会搜索任何管道字符及其后面的任何字符。
找到的任何内容都会从结果中删除。
如果您愿意,我可以更详细地解释RegEx。