Regex 哪种正则表达式方法最适合验证用户输入?(对于带delims的/f与echo%var%| Findstr/ri)

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 |

我想验证用户的输入,并将输入限制为字母数字字符(也可以使用下划线),但我不确定哪种方法最适合

我看到了关于SA的各种例子,第一个给我提出一些问题的例子是:

: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