Mat M es correcta acerca de la limitación de FINDSTR. El soporte de expresiones regulares FINDSTR es muy primitivo y no estándar. Escriba HELP FINDSTR
o FINDSTR /?
desde la línea de comandos para obtener una breve sinopsis de lo que es compatible. Para una explicación detallada, refiérase a What are the undocumented features and limitations of the Windows FINDSTR command?
Me gusta el comentario de Harry Johnston - Sería bastante fácil crear una solución usando VBScript o JavaScript. Creo que sería una opción mucho mejor.
Pero, aquí hay una solución nativa por lotes. Incorporé la regla adicional sobre la cantidad de subpatrones que el OP indicó en el comentario a la respuesta de Mat M.
La solución es sorprendentemente difícil. Los caracteres especiales pueden causar problemas al conectar la salida de ECHO a FINDSTR debido a la forma en que funcionan las tuberías. Cada lado de la tubería se ejecuta en su propia sesión de CMD. Los caracteres especiales deben ser citados, escapados dos veces o solo expuestos a través de una expansión demorada. Elegí usar la expansión retrasada, pero los caracteres !
deben escaparse dos veces para asegurarse de que la expansión retrasada ocurra en el momento correcto.
La manera más fácil de analizar un número variable de subpatrones es reemplazar el delimitador por una nueva línea y usar FOR/F para iterar cada subpatrón.
La mitad superior de mi código es un arnés de codificación frágil para iterar y probar convenientemente un conjunto de cadenas. No funcionará correctamente con ninguno de <space>
;
,
=
<tab>
*
o ?
en la cadena. Además, las comillas deben estar balanceadas en cada cadena.
Pero la rutina de validación más importante puede manejar cualquier cadena en la variable 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
Éstos son los resultados después de ejecutar el archivo por lotes
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")
actualización
La rutina :validate
se puede simplificar un poco al posponer la habilitación de expansión retardada hasta después de la CMD /V:ON
tubo. Esto significa que ya no tengo que preocuparme por el doble escape del !
en el lado izquierdo de la tubería.
: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
Si es posible, probablemente sea mejor que use vbscript o powershell. La manipulación de cadenas que contienen caracteres especiales es absurdamente difícil en los archivos por lotes de Windows. –
@Harry Johnston Desafortunadamente, no puedo usar nada más que comandos estándar internos o externos para cmd.exe. – networkcode
VBScript y JScript son utilidades nativas estándar disponibles para CMD.EXE, con buena compatibilidad con expresiones regulares. PowerShell es nativo desde Vista en adelante, y también tiene buen soporte de expresiones regulares. – dbenham