问题描述
|
我试图在文本中查找所有部分(并用其他替换)
从...开始 \'/\'
以。。结束 \'/\'
在两个/ \之间,除了字符串\'。\'和\'.. \'外,什么都可以。
(对于您的信息,我正在搜索并替换目录和文件名,因此应排除\'。\'和\'.. \'。)
这是我想出的正则表达式:
/(?!\\.|\\.\\.)([^/]+)/
第二部分
([^/]+)
匹配每个字符序列,不包括\'/ \'。不需要字符限制,我只是在解释输入内容。
第一部分
(?!\\.|\\.\\.)
使用否定的超前断言排除字符串\'。\'和\'.. \'。
但是,这似乎不适用于mb_ereg_replace()的PHP。
有人可以帮我吗?我看不到我的正则表达式有什么问题。
谢谢。
解决方法
POSIX正则表达式可能不支持负前瞻。 (尽管我可能是错的)
无论如何,由于PCRE regex通常比POSIX快,我认为您可以使用相同功能的PCRE版本,因为PCRE也支持utf8并使用
u
标志。
考虑以下代码作为替代:
preg_replace(\'~/(?!\\.|\\.\\.)([^/]+)/~u\',\"\",$str);
编辑:更好的是使用:
preg_replace(\'~/(?!\\.)([^/]+)/~u\',$str);
, 这有点冗长,但确实可以使用:
#/((\\.[^./][^/]*)|(\\.\\.[^/]+)|([^.][^/]*))/#
^ |------------| |---------| |---------|
| | | |
| | text starting with |
| | two dots,that isn\'t |
| | \".\" or \"..\" |
| text starting with |
| a dot,that isn\'t text not starting
| \".\" or \"..\" with a dot
|
delimiter
不匹配:
hi
//
/./
/../
符合:
/hi/
/.hi/
/..hi/
/...
/
在http://regexpal.com/上尝试一下。
我不确定你是否愿意付//
。如果这样做,请在最后一个/
之前贴*
。
, 我不反对正则表达式,但是我应该这样做:
function simplify_path($path,$directory_separator = \"/\",$equivalent = true){
$path = trim($path);
// if it\'s absolute,it stays absolute:
$prepend = (substr($path,1) == $directory_separator)?$directory_separator:\"\";
$path_array = explode($directory_separator,$path);
if($prepend) array_shift($path_array);
$output = array();
foreach($path_array as $val){
if($val != \'..\' || ((empty($output) || $last == \'..\') && $equivalent)) {
if($val != \'\' && $val != \'.\'){
array_push($output,$val);
$last = $val;
}
} elseif(!empty($output)) {
array_pop($output);
}
}
return $prepend.implode($directory_separator,$output);
}
测试:
echo(simplify_path(\"../../../one/no/no/../../two/no/../three\"));
// => ../../../one/two/three
echo(simplify_path(\"/../../one/no/no/../../two/no/../three\"));
// => /../../one/two/three
echo(simplify_path(\"/one/no/no/../../two/no/../three\"));
// => /one/two/three
echo(simplify_path(\".././../../one/././no/./no/../../two/no/../three\"));
// => ../../../one/two/three
echo(simplify_path(\".././..///../one/.///./no/./no/../../two/no/../three/\"));
// => ../../../one/two/three
我认为最好返回一个等效的字符串,因此在字符串开始时我尊重..
的出现。
如果您不想要它们,则可以使用第三个参数$ equivalent = false调用它:
echo(simplify_path(\"../../../one/no/no/../../two/no/../three\",\"/\",false));
// => one/two/three
echo(simplify_path(\"/../../one/no/no/../../two/no/../three\",false));
// => /one/two/three
echo(simplify_path(\"/one/no/no/../../two/no/../three\",false));
// => /one/two/three
echo(simplify_path(\".././../../one/././no/./no/../../two/no/../three\",false));
// => one/two/three
echo(simplify_path(\".././..///../one/.///./no/./no/../../two/no/../three/\",false));
// => one/two/three
, /(?!(\\.|\\.\\.)/)([^/]+)/
这将允许使用“ 23”作为有效名称。