示例1:domain.com/dir_1/dir_2/dir_3/./../../../
应在浏览器中自然解析为= domain.com/
示例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 :(得分:8)
这是一个更简单的问题,然后你正在考虑它。您需要做的只是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);
这将正确解析所有测试用例中的网址。
请注意,错误检查会留给用户进行练习(例如,当$parents
堆栈为空并且您尝试从其中弹出一些内容时)。
答案 1 :(得分:1)
这里你想要的是“replaceDots”功能。
它通过记住最后一个有效项目的位置来工作,然后如果你得到点,然后删除该项目。完整说明在此处“删除点细分”http://tools.ietf.org/html/rfc3986。在RFC页面上搜索删除点段。
您需要多个循环。内部循环向前扫描并查看下一部分,然后如果它是点,则跳过当前部分等,但它可能比这更棘手。或者考虑将其分解为部分然后遵循算法。
虽然输入缓冲区不为空,但循环如下:
一个。如果输入缓冲区以前缀“../”或“./”开头, 然后从输入缓冲区中删除该前缀;否则,
B中。如果输入缓冲区以前缀“/./”或“/。”开头, 在哪里“。”是一个完整的路径段,然后替换它 输入缓冲区中带有“/”的前缀;否则,
℃。如果输入缓冲区以前缀“/../”或“/ ..”开头, 其中“..”是一个完整的路径段,然后替换它 输入缓冲区中带有“/”的前缀,并删除最后一个 段及其前面的“/”(如果有的话)来自输出 缓冲;否则,
d。如果输入缓冲区仅包含“。”或“..”,然后删除 来自输入缓冲区;否则,
电子。将输入缓冲区中的第一个路径段移动到结尾 输出缓冲区,包括初始“/”字符(如果 任何)和任何后续角色,但不包括, 下一个“/”字符或输入缓冲区的结尾。
它通过记住最后一个有效项目的位置来工作,然后如果你得到点,然后删除该项目。完整描述在这里
这是我在C ++中的一个版本......
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;
}