我正在使用一些正则表达式在PHP中用于验证通过表单传递的UNC路径。它的格式应为:
\\server\something
...并允许进一步的子文件夹。为了保持一致性而剥离尾部斜杠可能是件好事,尽管如果需要的话我可以用substr轻松地做到这一点。
我在线阅读在PHP中匹配单个反斜杠需要4个反斜杠(当使用“C like string”时)并且我想我明白为什么(PHP转义(例如2 = 1,所以4 = 2),然后正则表达式引擎转义(剩下的2 = 1)。我已经看到以下两个引用为等效的合适的正则表达式来匹配单个反斜杠:
$regex = "/\\\\/s";
或显然这也是:
$regex = "/[\\]/s";
然而,这些产生了不同的结果,这与我最终目标相匹配,以匹配完整的UNC路径。
要查看我是否可以匹配两个反斜杠,我使用以下内容进行测试:
$path = "\\\\server";
echo "the path is: $path <br />"; // which is \\server
$regex = "/\\\\\\\\\/s";
if (preg_match($regex, $path))
{
echo "matched";
}
else
{
echo "not matched";
}
上面似乎匹配两个或更多反斜杠:(模式为8斜杠,转换为2,那么为什么3个反斜杠($path = "\\\\\\server"
)的输入匹配?
我想也许以下方法可行:
$regex = "/[\\][\\]/s";
再次,不:(
在我跳出窗户之前请帮助大声笑:)
答案 0 :(得分:6)
使用这个小宝石:
$UNC_regex = '=^\\\\\\\\[a-zA-Z0-9-]+(\\\\[a-zA-Z0-9`~!@#$%^&(){}\'._-]+([ ]+[a-zA-Z0-9`~!@#$%^&(){}\'._-]+)*)+$=s';
来源:http://regexlib.com/REDetails.aspx?regexp_id=2285(采用PHP字符串转义)
上面显示的RegEx匹配有效主机名(只允许几个有效字符)和主机名后面的路径部分(允许多个但不是所有字符)
关于反斜杠问题的旁注:
"
) to enclose your string时,您必须了解PHP特殊字符转义。"\\"
是PHP中的单个\
。 '
),也必须转义这些反斜杠。 \\
)被解释为单个反斜杠。'C:\\*.*'
=&gt; C:\*.*
)\'
)被解释为单引号。 'I\'ll be back'
=&gt; I'll be back
)'Just a \ somewhere'
=&gt; Just a \ somewhere
)\
视为字符类,因此您需要再次为RegEx转义它。 \\
,您必须写$regex = "\\\\\\\\"
或$regex = '\\\\\\\\'
单引号和双引号PHP字符串具有反斜杠的特殊含义。因此,如果\必须与正则表达式\匹配,则必须在PHP代码中使用“\\”或“\\”。
关于你的问题:
为什么输入3个反斜杠($ path =“\\\ server”)与正则表达式
"/\\\\\\\\/s"
匹配?
原因是您没有定义边界(使用^
作为开头,$
作为字符串结尾),因此它找到\\
“某处”导致积极的匹配。要获得预期的结果,您应该执行以下操作:
$regex = '/^\\\\\\\\[^\\\\]/s';
以上RegEx有两项修改:
^
在开头只匹配字符串开头的两个\\
[^\\]
否定字符类说:没有后跟一个额外的反斜杠关于你上一次的RegEx:
$regex = "/[\\][\\]/s";
你有一个混乱(见上文澄清),反斜杠在这里逃避。 PHP将"/[\\][\\]/s"
解释为/[\][\]/s
,这将使RegEx失败,因为\
是RegEx中的保留字符,因此必须进行转义。
您的RegEx的这个变体可以使用,但匹配任何两个反斜杠的出现的原因与上面已经解释的相同:
$regex = '/[\\\\][\\\\]/s';
答案 1 :(得分:3)
也回显你的正则表达式,所以你看到实际模式是什么,在PHP中编写这些斜杠对于模式来说可能变得很笨拙,所以你可以验证它是正确的。
此外,您应该将^
放在模式的开头,以便从字符串start和$
匹配到结尾,以指定必须匹配整个字符串。
\\server\something
正则表达式:
~^\\\\server\\something$~
PHP字符串:
$pattern = '~^\\\\\\\\server\\\\something$~';
对于重复,您想要说服务器存在,然后是一个或多个\something
部分。如果服务器就像某样东西,可以简化:
^\\(?:\\[a-z]+){2,}$
PHP字符串:
$pattern = '~^\\\\(?:\\\\[a-z]+){2,}$~';
由于在单引号字符串中应该如何编写\
字符存在一些混淆:
# Output:
#
# * Definition as '\\' ....... results in string(1) "\"
# * Definition as '\\\\' ..... results in string(2) "\\"
# * Definition as '\\\\\\' ... results in string(3) "\\\"
$slashes = array(
'\\',
'\\\\',
'\\\\\\',
);
foreach($slashes as $i => $slashed) {
$definition = sprintf('%s ', var_export($slashed, 1));
ob_start();
var_dump($slashed);
$result = rtrim(ob_get_clean());
printf(" * Definition as %'.-12s results in %s\n", $definition, $result);
}