regex-排除字符串的超前查询

问题描述

| 我试图在文本中查找所有部分(并用其他替换) 从...开始 \'/\' 以。。结束 \'/\' 在两个/ \之间,除了字符串\'。\'和\'.. \'外,什么都可以。 (对于您的信息,我正在搜索并替换目录和文件名,因此应排除\'。\'和\'.. \'。) 这是我想出的正则表达式:
/(?!\\.|\\.\\.)([^/]+)/
第二部分
([^/]+)
匹配每个字符序列,不包括\'/ \'。不需要字符限制,我只是在解释输入内容。 第一部分
(?!\\.|\\.\\.)
使用否定的超前断言排除字符串\'。\'和\'.. \'。 但是,这似乎不适用于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”作为有效名称。