在FINDSTR中使用子模式

net*_*ode 5 regex windows cmd batch-file findstr

我必须检查存储在变量中的字符串的有效性,我不能使用外部CLI实用程序(grep,awk等),所以我选择了FINDSTR.该字符串具有此格式(在regexp中):

([1-9][0-9]*:".*"(|".*")*)
Run Code Online (Sandbox Code Playgroud)

我不知道如何检查子模式(|."*").目前我的代码是:

((ECHO.) | (SET /P "=(11:"a"|"b"|"c")") | (FINDSTR /R /C:"^([1-9][0-9]*:".*")$"))
Run Code Online (Sandbox Code Playgroud)

问候.

dbe*_*ham 6

Mat M对FINDSTR的限制是正确的.FINDSTR正则表达式支持非常原始且非标准.键入HELP FINDSTRFINDSTR /?从命令行输入所需内容的简要概要.有关深入解释,请参阅Windows FINDSTR命令的未记录的功能和限制是什么?

我喜欢Harry Johnston的评论 - 使用VBScript或JavaScript创建解决方案非常容易.我认为这将是一个更好的选择.

但是,这是一个本地批处理解决方案.我已经将关于OP的子模式数量的额外规则纳入Mat M的答案评论中.

解决方案令人惊讶地棘手.由于管道的工作方式,将ECHO输出管道输送到FINDSTR时,特殊字符可能会导致问题.管道的每一侧都在它自己的CMD会话中执行.特殊字符必须引用,转义两次,或仅通过延迟扩展公开.我选择使用延迟扩展,但!必须对字符进行两次转义,以确保在正确的时间发生延迟扩展.

解析可变数量的子模式的最简单方法是用换行符替换分隔符,并使用FOR/F迭代每个子模式.

我的代码的上半部分是一个脆弱的编码工具,可以方便地迭代和测试一组字符串.它不会有任何的正常工作<space> ; , = <tab> *?在字符串.此外,引号必须在每个字符串中平衡.

但更重要的验证例程可以处理var变量中的任何字符串.

@echo off
setlocal
set LF=^


::Above 2 blank lines are critical for creating a linefeed variable. Do not remove

set test=a

for %%S in (
  "(3:"a"|"c"|"c")"
  "(11:"a"|"b"|"c"|"d"|"esdf"|"f"|"g"|"h"|"i"|"j"|"k")"
  "(4:"a"|"b"|"c")"
  "(10:"a"|"b"|"c"|"d"|"esdf"|"f"|"g"|"h"|"i"|"j"|"k")"
  "(3:"a"|"b"|"c""
  "(3:"a"|"b^|c")"
  "(3:"a"|"b"|c)"
  "(3:"a"|"b"||"c")"
  "(3:"a"|"b"|;|"c")"
) do (
  set "var=%%~S"
  call :validate
)
exit /b

:validate
setlocal enableDelayedExpansion
cmd /v:on /c echo ^^^!var^^^!|findstr /r /c:"^([1-9][0-9]*:.*)$" >nul || (call :invalid  FINDSTR fail& exit /b)
if "!var:||=!" neq "!var!" (call :invalid double pipe fail& exit /b)
for /f "delims=(:" %%N in ("!var!") do set "expectedCount=%%N"
set "str=!var:*:=!"
set "str=!str:~0,-1!"
set foundCount=0
for %%A in ("!LF!") do for /f eol^=^%LF%%LF%^ delims^=  %%B in ("!str:|=%%~A!") do (
  if %%B neq "%%~B" (call :invalid sub-pattern fail& exit /b)
  set /a foundCount+=1
)
if %foundCount% neq %expectedCount% (call :invalid count fail& exit /b)
echo Valid: !var!
exit /b
:invalid
echo Invalid - %*: !var!
exit /b
Run Code Online (Sandbox Code Playgroud)

以下是运行批处理脚本后的结果

Valid: (3:"a"|"c"|"c")
Valid: (11:"a"|"b"|"c"|"d"|"esdf"|"f"|"g"|"h"|"i"|"j"|"k")
Invalid - count fail: (4:"a"|"b"|"c")
Invalid - count fail: (10:"a"|"b"|"c"|"d"|"esdf"|"f"|"g"|"h"|"i"|"j"|"k")
Invalid - FINDSTR fail: (3:"a"|"b"|"c"
Invalid - sub-pattern fail: (3:"a"|"b|c")
Invalid - sub-pattern fail: (3:"a"|"b"|c)
Invalid - double pipe fail: (3:"a"|"b"||"c")
Invalid - sub-pattern fail: (3:"a"|"b"|;|"c")
Run Code Online (Sandbox Code Playgroud)


更新

:validate例程可以通过推迟延迟扩展的启用,直到之后被简化有点CMD /V:ON管.这意味着我不再需要担心双重逃离!管道的左侧.

:validate
cmd /v:on /c echo !var!|findstr /r /c:"^([1-9][0-9]*:.*)$" >nul || (call :invalid  FINDSTR fail& exit /b)
setlocal enableDelayedExpansion
... remainder unchanged
Run Code Online (Sandbox Code Playgroud)