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

脚本'n'代码

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

我在 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

)

最后FOR /F我在这里也注意到了循环方法:

for /f "delims=1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ" %%a in ("%in%") do goto :input

与前面提到的 FINDSTR 正则表达式相比,使用它是否有任何(不利)优势?

aschipfl

为了安全地验证用户输入,这两种方法都是可靠的,但您必须改进它们:


findstr 方法

首先,让我们关注这样的搜索字符串^[...][...]*$(其中...代表一个字符类,意思是一组字符):一个字符类[...]匹配集合中的任何一个字符...*表示重复,因此匹配零次或多次出现,因此[...]*匹配 set 中出现的零次或多次字符...因此,[...][...]*匹配 set 中出现的一个或多个字符...前导^将匹配锚定到行的开头,尾随$将其锚定到行尾;因此,当指定了两个锚点时,整行必须与搜索字符串匹配。

关于字符类[...]:根据线程Windows FINDSTR 命令的未记录功能和限制是什么?,课程有问题;例如,该类[A-Z]将小写字母匹配bz,并将[a-z]大写字母匹配AY(这当然无关紧要,如果进行了不区分大小写的搜索,因此何时/I给出);[0-9]可能匹配²³,具体取决于当前代码页;[A-Z]并且[a-z]可能匹配特殊字母,例如Áá,也取决于当前代码页。因此,为了仅安全地匹配某些字符,不要使用范围,而是单独指定每个字符,例如[0123456789][ABCDEFGHIJKLMNOPQRSTUVWXYZ][abcdefghijklmnopqrstuvwxyz]

所有这些都引导我们进入以下findstr命令行:

findstr /R /I "^[0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ][0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ]*$"

尽管如此,使用管道的整个方法echo可能仍然会失败,因为像", &, ^, %, !, (, ), <, >,等特殊字符|可能会导致语法错误或其他意外行为。为避免这种情况,我们需要建立延迟扩展,以便特殊字符对命令解析器隐藏。但是,由于管道 ( |)cmd为任一侧(继承当前环境初始化了新实例,我们需要确保在左子cmd实例中而不是在父实例中进行实际的变量扩展,如下所示:

:INPUT
set "IN="
set /P IN="Please enter your username: "

cmd /V /C echo(^^!IN^^!| findstr /R /I "^[0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ][0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ]*$" > nul || goto :INPUT

cmd需要额外的显式实例来启用延迟扩展 ( /V),因为管道启动的实例已禁用延迟扩展。

感叹号的双重转义^^!仅在父cmd实例中也启用了延迟扩展的情况下才需要如果没有,单次转义^!就足够了,但双次转义也无妨。


for /F 方法

这种方法使生活更轻松,因为不涉及管道,因此您不必处理多个cmd实例,但仍有改进的空间。同样,特殊字符可能会引起麻烦,因此需要启用延迟扩展。

for /F循环忽略空行和这样的开始与默认eol字符,分号;要禁用该eol选项,只需定义一个分隔符,因此eol隐藏在delims. 空行不会被迭代,因此在goto用户输入为空的情况下,您的方法中命令永远不会执行。因此,我们必须使用if语句显式捕获空的用户输入现在所有这些都导致了以下代码:

setlocal EnableDelayedExpansion
:INPUT
set "IN="
set /P IN="Please enter your username: "

if not defined IN goto :INPUT
for /F "delims=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ eol=0" %%Z in ("!IN!") do goto :INPUT

endlocal

这种方法只检测大写字母;要包括小写字母,您必须将它们添加到delims选项中:delims=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.

请注意,变量IN不再可用endlocal,但无论如何这应该是脚本的最后一个命令。

为了检测for /F循环是否迭代,有一个未公开的特性,我们可以利用它:for /F如果没有迭代,则返回非零退出代码,因此可以使用条件执行运算符&&||所以,当用户输入为空时,循环不迭代,然后||为此,for /F循环必须括在括号内:

setlocal EnableDelayedExpansion
:INPUT
set "IN="
set /P IN="Please enter your username: "

if not defined IN goto :INPUT
(for /F "delims=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ eol=0" %%Z in ("!IN!") do rem/) && goto :INPUT

endlocal

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

哪种方法最适合在JavaScript中创建对象?对象属性之前是否必须使用“ var”?

jax-ws ri 2.2.1对于Amazon ECS wsdl文件未生成任何枚举

Golang html /模板:带有自定义Delims的ParseFiles

如何使用delims分割文件?

在cmd中使用“ set var = text”命令后,为什么没有带有'echo%var%'的字符串输出?

如何禁用for / F的eol和delims选项?

对于/ f delims:忽略一行中第二次出现delim-character

Findstr-仅返回正则表达式匹配项

ri中记录的关键字方法参数在哪里?

模块“ rpy2.robjects.pandas2ri”没有属性“ ri2py”

如何仅将grep -f与变量一起使用,例如在echo“ pattern”中作为输入| grep -f-<<< $ var?

delims中的双引号=?

Python:带有原始f字符串的正则表达式只能在50%的时间内工作

如何在findstr实用程序中使用单词边界正则表达式

确定最适合正则表达式

FINDSTR中的正则表达式和文字表达式有什么区别?

回声%var%打印FINDSTR参数

使用正则表达式的FindStr

Findstr:带有变量的正则表达式

带有echo findstr的批处理文件在for循环内不起作用

[Echo!file!| findstr]中的管道错误

echo $var 和 echo "$var" 有什么区别

我如何正则表达式匹配 bash 中的文件名?即 tail -f /var/log/(syslog|mail.log)

使用 /f delims 获取子字符串并保留所有分隔符

对于 /F findstr 设置 CSV 的第二列值

RMarkdown 塊中的多個 Flextables(帶有 echo = F)不呈現

在“delims”之后批量包含“空格”

对于带有 delims 的 /f 循环进行拆分并使用字符串仅运行一次(批处理)

`\f` 的正则表达式