正则表达式 - 负向前瞻以排除字符串

时间:2011-06-14 22:27:18

标签: php regex expression

我试图在文本的所有部分中找到(并用其他东西替换)

  1. 以'/'
  2. 开头
  3. 以'/'
  4. 结尾
  5. 两者之间可以有任何东西,除了字符串'。'和'..'。
  6. (有关您的信息,我正在搜索并替换目录和文件名,因此应排除'。'和'..'。)

    这是我提出的正则表达式:

    /(?!\.|\.\.)([^/]+)/
    

    第二部分

    ([^/]+)
    

    匹配每个字符序列,'/'被排除在外。不需要字符限制,我只是解释输入。

    第一部分

    (?!\.|\.\.)
    

    使用负前瞻断言来排除字符串'。'和'..'。

    但是,这似乎不适用于使用mb_ereg_replace()的PHP。

    有人可以帮帮我吗?我没有看到我的正则表达式出了什么问题。

    谢谢。

4 个答案:

答案 0 :(得分:4)

POSIX正则表达式可能不支持负向前瞻。 (虽然我可能错了)

无论如何,因为PCRE正则表达式通常比POSIX快,我认为你可以使用相同功能的PCRE版本,因为PCRE支持utf8以及使用u标志。

将此代码视为替代:

preg_replace('~/(?!\.|\.\.)([^/]+)/~u', "", $str);

编辑:更好的是使用:

preg_replace('~/(?!\.)([^/]+)/~u', "", $str);

答案 1 :(得分:3)

这有点冗长,但它确实有效:

#/((\.[^./][^/]*)|(\.\.[^/]+)|([^.][^/]*))/#
^  |------------| |---------| |---------|
|        |             |               |
|        |        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/上进行游戏。

我不确定您是否允许//。如果您这样做,请在最后*之前坚持/

答案 2 :(得分:1)

我不反对正则表达式,但我会这样做:

function simplify_path($path, $directory_separator = "/", $equivalent = true){
  $path = trim($path);
  // if it's absolute, it stays absolute:
  $prepend = (substr($path,0,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

答案 3 :(得分:0)

/(?!(\.|\.\.)/)([^/]+)/ 这将允许...作为有效名称。