2013-02-14 72 views
3

實施例1:domain.com/dir_1/dir_2/dir_3/./../../../
如果在瀏覽器中自然分解爲= domain.com/解析相對路徑中的URL與PHP

實施例2:domain.com/dir_1/dir_2/dir_3/./../../../test/././../new_dir/
應解析成domain.com/new_dir/

實施例3:domain.com/dir_1/dir_2/dir_3/./../../../test/dir4/../final
應顯示爲domain.com/test/final

的問題是...我怎麼可以通過串遍歷做到這一點?我覺得像for()循環將得到在這一點迷茫..

Transfrom relative path into absolute URL using PHP

PHP: How to resolve a relative url

不爲我在這種情況下工作..我不應該需要一個參考點(基地),因爲客觀上收拾東西我已經有..

+0

你能詳細說明你的具體情況是什麼嗎?也許有一種更簡單的方法可以做任何你想做的事情。 – 2013-02-14 20:34:07

+0

你沒有嘗試過3種來自pguardiario的帖子的工具,在他的評論中鏈接到你鏈接的第二個問題上? – qdinar 2016-01-03 16:13:22

回答

7

這是一個比較簡單的問題,那麼你正在考慮這個問題。您需要做的就是/字符explode(),並使用堆棧解析出所有單獨的段。當您從左向右遍歷數組時,如果看到.,則什麼也不做。如果您看到..,請從堆棧中彈出一個元素。否則,將一個元素推入堆棧。

$str = 'domain.com/dir_1/dir_2/dir_3/./../../../'; 
$array = explode('/', $str); 
$domain = array_shift($array); 

$parents = array(); 
foreach($array as $dir) { 
    switch($dir) { 
     case '.': 
     // Don't need to do anything here 
     break; 
     case '..': 
      array_pop($parents); 
     break; 
     default: 
      $parents[] = $dir; 
     break; 
    } 
} 

echo $domain . '/' . implode('/', $parents); 

這將正確解析所有測試用例中的URL。

請注意,錯誤檢查留給用戶作爲練習(即當$parents堆棧爲空並且您試圖從中彈出某些東西時)。

1

你想在這裏什麼是「replaceDots」功能。

它通過記住最後一次的有效項目的位置,然後如果你點然後移除該項目。完整的描述在這裏「刪除點段」http://tools.ietf.org/html/rfc3986。在RFC頁面搜索刪除點段。

你需要不止一個循環。內部循環提前掃描並查看下一部分,然後如果它是點,則當前部分被跳過等,但可能比這更棘手。或者考慮將其分解成多個部分,然後遵循該算法。

  1. 當輸入緩衝器不爲空,循環如下:

    A.如果輸入緩衝器與「../」或「./」前綴開始, 然後刪除該前綴來自輸入緩衝區;否則,

    B.如果輸入緩衝區以「/./」或「/。」的前綴開頭,則其中「。」爲 。是一個完整的路徑段,然後用輸入緩衝區中的「/」替換前綴 ;否則,

    C.如果輸入緩衝器開始於「/../」或「/ ..」, 的前綴,其中「..」是一個完整的路徑段,然後替換 前綴「/從輸出緩衝器 「在輸入緩衝器和刪除最後 段及其前面的‘/’(如果有的話);否則,

    D.如果輸入緩衝器僅由「」或「..」,然後從輸入緩衝區中刪除 ;否則,

    E.移動在輸入緩衝器中的第一個路徑段的 端部的輸出緩衝器,包括最初的「/」字符(如果 有的話)和任何後續字符爲止,但不包括 下一個「/」字符或輸入緩衝區的結尾。

    1. 最後,輸出緩衝區由於 remove_dot_segments而返回。功能。

它通過記住最後一次的有效項目的位置,然後如果你點然後移除該項目。完整的描述在這裏

這裏是我的IN C版本的IT ++ ...

ortl_funcimp(len_t) _str_remove_dots(char_t* s, len_t len) { 
    len_t x,yy; 
    /* 
    Modifies the string in place by copying parts back. Not 
    sure if this is the best way to do it since it involves 
    many copies for deep relatives like ../../../../../myFile.cpp 

    For each ../ it does one copy back. If the loop was implemented 
    using writing into a buffer, you would have to do both, so this 
    seems to be the best technique. 
    */ 
    __checklenx(s,len); 
    x = 0; 
    while (x < len) { 
    if (s[x] == _c('.')) { 
     x++; 
     if (x < len) { 
     if (s[x] == _c('.')) { 
      x++; 
      if (x < len) { 
      if (s[x] == _c('/')) { // ../ 
       mem_move(&s[x],&s[x-2],(len-x)*sizeof(char_t)); 
       len -= 2; 
       x -= 2; 
      } 
      else x++; 
      } 
      else len -= 2;// .. only 
     } 
     else if (s[x] == _c('/')){ // ./ 
      mem_move(&s[x],&s[x-1],(len-x)*sizeof(char_t)); 
      len--; 
      x--; 
     } 
     } 
     else --len;// terminating '.', remove 
    } 
    else if (s[x] == _c('/')) { 
     x++; 
     if (x < len) { 
     if (s[x] == _c('.')) { 
      x++; 
      if (x < len) { 
      if (s[x] == _c('/')) { // /./ 
       mem_move(&s[x],&s[x-2],(len-x)*sizeof(char_t)); 
       len -= 2; 
       x -= 2; 
      } 
      else if (s[x] == _c('.')) { // /.. 
       x++; 
       if (x < len) { // 
       if (s[x] == _c('/')) {// /../ 
        yy = x; 
        x -= 3; 
        if (x > 0) x--; 
        while ((x > 0) && (s[x] != _c('/'))) x--; 
        mem_move(&s[yy],&s[x],(len-yy) * sizeof(char_t)); 
        len -= (yy - x); 
       } 
       else { 
        x++; 
       } 
       } 
       else {// ends with /.. 
       x -= 3; 
       if (x > 0) x--; 
       while (x > 0 && s[x] != _c('/')) x--; 
       s[x] = _c('/'); 
       x++; 
       len = x; 
       } 
      } 
      else x++; 
      } 
      else len--;// ends with /. 
     } 
     else x++; 
     } 
    } 
    else x++; 
    } 
    return len; 
}