Regex 哪种正则表达式方法最适合验证用户输入?(对于带delims的/f与echo%var%| Findstr/ri)
我想验证用户的输入,并将输入限制为字母数字字符(也可以使用下划线),但我不确定哪种方法最适合 我看到了关于SA的各种例子,第一个给我提出一些问题的例子是:Regex 哪种正则表达式方法最适合验证用户输入?(对于带delims的/f与echo%var%| Findstr/ri),regex,batch-file,for-loop,findstr,Regex,Batch File,For Loop,Findstr,我想验证用户的输入,并将输入限制为字母数字字符(也可以使用下划线),但我不确定哪种方法最适合 我看到了关于SA的各种例子,第一个给我提出一些问题的例子是: :input set "in=" set /p "in=Please enter your username: " ECHO(%in%|FINDSTR /ri "^[0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ][0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ]*$" >nul |
:input
set "in="
set /p "in=Please enter your username: "
ECHO(%in%|FINDSTR /ri "^[0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ][0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ]*$" >nul || (
goto input
)
我看到第二个案例与第一个案例相同(正如预期的那样,前导的^
和结尾的*$
)
为什么在以下条件也起作用的情况下,还需要额外的案例和^
*$
:input
set "in="
set /p "in=Please enter your username: "
ECHO(%in%|FINDSTR /ri "[0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ]" >nul || (
goto input
)
最后,我在这里也注意到了/F的循环方法:
for /f "delims=1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ" %%a in ("%in%") do goto :input
与前面提到的FINDSTR regex one相比,使用它有任何(不利)的优势吗?首先,您必须使用延迟扩展引用
中的环境变量,以避免在用户输入带有关键字符(如的字符串)时由于语法错误退出批处理文件执行,您必须使用延迟扩展引用
中的环境变量,以避免由于语法错误而退出批处理文件执行。当用户输入带有关键字符(如)的字符串时,为了安全验证用户输入,这两种方法都是可靠的,但您必须改进它们:
方法
首先,让我们关注搜索字符串,如^[…][…]*$
(其中..
表示字符类,表示一组字符):字符类[…]
匹配集合..
中的任何一个字符*
表示重复,因此匹配零次或多次出现,因此[…]*
匹配集合..
中零次或多次出现的字符;因此,[…][…]*
匹配集合..
中出现的一个或多个字符。前导的^
将匹配锚定到行首,尾随的$
将匹配锚定到行尾;因此,当指定两个定位点时,整行必须与搜索字符串匹配
关于字符类[…]
:根据线程,类是有缺陷的;例如,类[A-Z]
将小写字母b
匹配到Z
,而[A-Z]
将大写字母A
匹配到Y
(在进行不区分大小写的搜索时,这当然无关紧要,在给出/I
时也是如此);类别[0-9]
可能匹配²
或³
,具体取决于当前代码页<代码>[A-Z]
和[A-Z]
可以匹配特殊字母,例如Á
或á
,这也取决于当前代码页。因此,为了仅安全地匹配某些字符,请不要使用范围,而是单独指定每个字符,如[0123456789]
,[ABCDEFGHIjklmnopqrStuvxyz]
或[ABCDEFGHIjklmnopqrStuvxyz]
所有这些导致我们进入以下findstr
命令行:
findstr/R/I“^[0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ][0123456789abcdefghijklmnopqrstuvxyz]*$”
然而,使用管道式回声的整个方法可能仍然失败,因为像“
,&
,^
,%
,!
,(
,)
,
,|
可能会导致语法错误或其他意外行为。为了避免这种情况,我们需要建立特殊字符,以便对命令解析器隐藏特殊字符。但是,由于为任意一方初始化新的cmd
实例(继承当前环境),我们需要确保在左边的子cmd
实例中而不是在父实例中进行实际的变量展开,如下所示:
:输入
设置“IN=”
set/P IN=“请输入您的用户名:”
cmd/V/C echo(^^!IN^!| findstr/R/I“^[0123456789ABCDEFGHIJKLMNOPQRSTUVXYZ][0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ]*$”>nul|转到:输入
需要额外显式的cmd
实例来启用延迟扩展(/V
),因为管道启动的实例已禁用延迟扩展
只有在父级cmd
实例中也启用了延迟扩展的情况下,才需要感叹号的双转义^!
;否则,单转义^!
就足够了,但双转义不会造成伤害
方法
这种方法使工作更轻松,因为不涉及管道,因此您不必处理多个cmd
实例,但仍有改进的余地。同样,特殊字符可能会导致问题,因此需要启用延迟扩展
忽略以默认的eol
字符开始的空行和分号;
。要禁用eol
选项,只需定义一个分隔符字符,这样eol
就隐藏在delims
后面。空行不会重复,因此在您的程序中使用goto
命令在用户输入为空的情况下,ch永远不会执行。因此,我们必须使用显式捕获空用户输入。现在,所有这些导致以下代码:
setlocal EnableDelayedExpansion
:输入
设置“IN=”
set/P IN=“请输入您的用户名:”
如果未在goto中定义:输入
对于/F“delims=0123456789abcdefghijklmnopqrstuvxyz eol=0”%%Z in(“!in!”)进行转到:输入
端部
此方法仅检测大写字母;要包括小写字母,您必须将它们添加到delims
选项:delims=0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvxyz
请注意,
中的变量在endlocal
之外不再可用,但这应该是脚本的最后一个comand
去