我尝试构建 RegExp 来验证(preg_match)以下两个规则的一些路径字符串:
- 路径必须仅包含给定范围内的符号
[a-zA-z0-9-_\///\.]
- 路径将不包含向上目录序列“..”
这是一个正确的路径示例:/user/temp
和坏的:/../user
UPD:
/user/temp.../foo
也是正确的(感谢Laurence Gonsalves)
我尝试构建 RegExp 来验证(preg_match)以下两个规则的一些路径字符串:
[a-zA-z0-9-_\///\.]
这是一个正确的路径示例:/user/temp
和坏的:/../user
UPD:
/user/temp.../foo
也是正确的(感谢Laurence Gonsalves)
考虑一下:
$right_path = '/user/temp';
$wrong_path = '/../user';
$almost_wrong_path = 'foo/abc../bar';
$almost_right_path = 'foo/../bar';
$pattern = '#^(?!.*[\\/]\.{2}[\\/])(?!\.{2}[\\/])[-\w.\\/]+$#';
var_dump(preg_match($pattern, $right_path)); // 1
var_dump(preg_match($pattern, $wrong_path)); // 0
var_dump(preg_match($pattern, $almost_wrong_path)); // 1
var_dump(preg_match($pattern, $almost_right_path)); // 0
我实际上分三个步骤构建了这个模式:
1) 给出的第一条规则说,字符串中只允许使用的符号是0-9
, a-zA-Z
, _
(下划线), -
(hyphen), .
(dot) 和斜线 (/
和\
)。前三个位置可以用快捷方式 ( \w
) 表示,其他位置需要字符类:
[-\w.\\/]
这里注意两点:1)连字符应该是字符类中的第一个或最后一个符号(否则它被视为用于定义范围的元字符);2)点和正斜杠都还没有转义(反斜杠被转义了;它太强大了,不能单独使用,即使在[...]
子表达式中也是如此)。
2) 现在我们必须确保模式确实覆盖了整个字符串。我们用所谓的锚点来做 -^
用于字符串的开头,$
用于结尾。而且,不要忘记我们的字符串可能包含一个或多个允许的符号(这用量词表示+
)。所以模式变成了这样:
^[-\w.\\/]+$
3)最后一件事——我们也必须防止使用../
and ..\
(如果序列开始字符串,则在/
or之前\
- 或不使用)。..[/\\]
表达此规则的最简单方法是使用所谓的“否定前瞻”测试。它写在 (?!...) 子表达式中,并且(在这种情况下)描述了以下想法:'确保零个或多个符号的序列后面没有“斜线-两个点-斜线”序列':
^(?!.*[\\/]\.{2}[\\/])(?!\.{2}[\\/])[-\w.\\/]+$
最后一件事实际上是将模式放入preg_match
函数中:当我们/
在正则表达式中使用符号时,我们可以选择另一组分隔符。在我的示例中,我选择了“#”:
$pattern = '#^(?!.*[\\/]\.{2}[\\/])(?!\.{2}[\\/])[-\w.\\/]+$#';
看?这真的很容易。) 你只需要从小事做起,逐步发展。