Php 我应该使用正则表达式,还是仅仅使用一系列if语句?
我需要根据以下规则验证字符串:Php 我应该使用正则表达式,还是仅仅使用一系列if语句?,php,javascript,regex,conditional,Php,Javascript,Regex,Conditional,我需要根据以下规则验证字符串: 值不是s 值的长度至少为1个字符 值仅包含a-z0-9-\uz/ 值不以/ 值不以/ 值不包含/s/ 值不包含/ 值不以s/ 值不以/s (更简单地说,我正在寻找类似UNIX风格的路径,带有斜杠分隔符,其中文件/文件夹名称只允许a-z0-9-,没有文件/文件夹命名为s,并且没有开头或结尾的斜杠。) 我需要通过JavaScript在客户端和使用PHP在服务器端执行此操作 我知道最优雅的解决方案是通过复杂的正则表达式。但它值得尝试写一个这样的挑战吗?或者我应该只使用条
s
a-z0-9-\uz/
/
/
/s/
/
s/
/s
a-z0-9-
,没有文件/文件夹命名为s
,并且没有开头或结尾的斜杠。)
我需要通过JavaScript在客户端和使用PHP在服务器端执行此操作
我知道最优雅的解决方案是通过复杂的正则表达式。但它值得尝试写一个这样的挑战吗?或者我应该只使用条件吗
现在,我的解决方案是:
JavaScript:
(function ($) {
var test = function (val) {
return
val != 's' &&
/^[a-z0-9-_\/]+$/.test(val) &&
val.substr(0, 1) != '/' &&
val.substr(val.length-1) != '/' &&
val.search('/s/') == -1 &&
val.search('//') == -1 &&
val.substr(0, 2) != 's/' &&
val.substr(val.length-2) != '/s';
};
$('#test')
.keyup(function () {
if (test($(this).val())) {
$(this).removeClass('fail').addClass('pass');
}
else {
$(this).removeClass('pass').addClass('fail');
}
)
.keyup();
})(jQuery);
PHP:
这种做法是否可以接受?我对正则表达式不是很在行,我也不知道如何为它编写一个正则表达式——但我忍不住觉得这更像是一个破解,而不是一个解决方案
你觉得怎么样
谢谢。请明确使用正则表达式:
if (preg_match('~^(?!s?/|s$)(?>[a-z0-9_-]++|/(?!s?/|s?$))++$~', $val)) {
// do that
}
图案详情:
~ # pattern delimiter
^ # start of the string
(?!s?/|s$) # negative lookahead (not followed by "s$", "/", "s/")
(?> # open an atomic group (can be replaced by "(?:")
[a-z0-9_-]++ # allowed characters except "/", one or more times
| # OR
/(?!s?/|s?$) # "/" not followed by "s/" or "/" or "$" or "s$"
)++ # close the group and repeat one or more times
$ # end of the string
~ # pattern delimiter
一个正则表达式相对于多个小正则表达式有什么优势
您只需遍历测试字符串一次,模式在第一个错误字符处失败
对于将来的调试,您可以使用详细模式和nowdoc使其更加清晰,例如:
$pattern = <<<'LOD'
~
^
(?!s?/|s$) # not followed by "s$", "/", "s/"
(?> [a-z0-9_-]++ | / (?!s?/|s?$) )++
$
~x
LOD;
注意:当您想将文字
-
放入字符类中时,必须始终在类的开头或结尾写入,因为它是用于定义字符范围的特殊字符。即使使用检查,您也应该通过将所有if合并为一个if来摆脱嵌套if。
下面是一个带有2个regexp的更简单的变体(第一个限制边缘情况,第二个检查允许的字符):
UPD:
哦,在我键入答案时,您删除了嵌套的IFs:)
好,好 针对多个和需求的单一正则表达式解决方案
下面是一个符合您需求的注释php正则表达式:(始终以这种方式编写非平凡正则表达式)
$re='%#验证*nix-like路径,带有多个规范。
^#锚定至管柱起点。
(!s$)#值不是s
(?=)#值的长度至少为1个字符
(?!/)#值不以开头/
(?!.*/$)#值不以结尾/
(?!*/s/)#值不包含/s/
(?!.*/)#值不包含//
(?!s/)#值不以s开头/
(?!*/s$)#值不以/s结尾
[\w\-/]+#值仅包含a-z0-9-_/
$#锚定到字符串末端。
%九",;
以下是等效的JavaScript版本:
var re=/^(?!s$)(?=)(?!\/)(?!.\/$)(?!.\/s\/)(?!.\/\/)(?!s\/)(?!.\\/s$)[\w\-\/]+$/i;
此解决方案假定您的需求不区分大小写。如果情况并非如此,则删除i
ignorecase修饰符(并将[\w\-/]+
表达式更改为[a-z0-9\-/]+
)
为了描述的清晰,我已经为您的每一个需求编写了注释版本,每行一个断言。与开头的^
锚定一起,每个先行断言都以逻辑和方式工作。请注意,(?=)
断言(确保存在一个字符)是多余的,因为最后一个表达式:[\w\-/]+
也确保长度至少为一个字符。请注意,^
和$
锚定都是此操作所必需的
此解决方案演示了如何在一个易于阅读和维护的正则表达式中实现多个需求。但是,出于其他原因,您可能希望将其拆分为单独的检查-例如,这样您的代码就可以为每个需求生成单独的有意义的错误消息。我认为您应该学习regex!!您不需要正则表达式,只需要取消嵌套if语句,但每个语句中都有一个fail。如果全部通过,则返回true。您~可能~可以~将所有这些条件塞进一个过于复杂的正则表达式中,但如果您将来需要编辑它,这将是一个巨大的麻烦。我通常将每个需求分解为一个正则表达式,将它们放入一个数组中,然后遍历它们。也就是说,我认为您在代码中实现它们的方式没有任何问题。另外,当我需要编写复杂的正则表达式时,我发现它非常有用。@Sammitch-我不同意。一个单一的正则表达式解决方案在以自由间距模式编写时是完美的、合适的(并且是快速的),并且有大量的注释和缩进。看看下面我的注释单正则表达式解决方案。您觉得它是否过于复杂或不可维护?也就是说,可以提出一个很好的理由来分解测试,以便为每个需求提供单独的错误消息。谢谢。我在制定解决方案时使用了嵌套的ifs,但它太庞大了。虽然现在我在想,我可能会把它分成几个检查,这样我就可以提供更有意义的错误消息(例如:if(!condition1)error(“请不要使用字符串的“.”);else if(!condition2).
。这在PHP中非常有效。但是(请原谅我对regex知之甚少),我猜它使用了look behinds,这是JavaScript不支持的,这意味着我无法验证客户端。@MMiller:是的,JavaScript和php之间的正则表达式功能是不同的。我已经编写了一个JavaScript版本。这正是我需要的,最好是你解释了表达式的每一部分。谢谢!你有
$pattern = <<<'LOD'
~
^
(?!s?/|s$) # not followed by "s$", "/", "s/"
(?> [a-z0-9_-]++ | / (?!s?/|s?$) )++
$
~x
LOD;
/^(?!s?\/|s$)(?:[a-z0-9_-]|\/(?!s?\/|s?$))+$/
if (
$val != 's'
&& !preg_match('!(^/|/s|s/|//|/$)!', $val)
&& preg_match('!^[a-z0-9-_/]+$!', $val)
) {
// ...
}