Mat M è corretto sulla limitazione di FINDSTR. Il supporto regex di FINDSTR è molto primitivo e non standard. Digitare HELP FINDSTR
o FINDSTR /?
dalla riga di comando per ottenere una breve sinossi di ciò che è supportato. Per una spiegazione approfondita, fare riferimento a What are the undocumented features and limitations of the Windows FINDSTR command?
Mi piace il commento di Harry Johnston - Sarebbe abbastanza facile creare una soluzione utilizzando VBScript o JavaScript. Penso che sarebbe una scelta molto migliore.
Ma, ecco una soluzione batch nativo. Ho incorporato la regola aggiuntiva sul numero di sottoprogrammi che l'OP ha dichiarato nel commento alla risposta di Mat M.
La soluzione è sorprendentemente complessa. Caratteri speciali possono causare problemi quando si esegue il piping dell'output ECHO a FINDSTR a causa del modo in cui i tubi funzionano. Ogni lato della pipe viene eseguito nella propria sessione CMD. I caratteri speciali devono essere citati, sfuggiti due volte o esposti solo tramite un'espansione ritardata. Ho scelto di utilizzare l'espansione ritardata, ma i caratteri !
devono essere sfuggiti due volte per assicurarsi che l'espansione ritardata avvenga all'ora corretta.
Il modo più semplice per analizzare un numero variabile di subtertern è sostituire il delimitatore con una nuova riga e utilizzare FOR/F per iterare ogni subpattern.
La metà superiore del mio codice è un'imbracatura di codifica fragile per semplificare l'iterazione e testare un set di stringhe. Non funzionerà correttamente con qualsiasi <space>
;
,
=
<tab>
*
o ?
nella stringa. Inoltre, le virgolette devono essere bilanciate in ogni stringa.
Ma la più importante routine di convalida può gestire qualsiasi stringa nella variabile 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
Ecco i risultati dopo l'esecuzione dello script batch di
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")
Aggiornamento
Il :validate
routine può essere semplificato un po 'posticipando l'abilitazione di espansione ritardata fino a dopo la CMD /V:ON
tubo. Ciò significa che non devo più preoccuparmi di eseguire il doppio escape del !
sul lato sinistro del tubo.
: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
Se possibile, probabilmente stai meglio usando vbscript o powershell. Manipolare le stringhe contenenti caratteri speciali è una difficoltà assurda nei file batch di Windows. –
@Harry Johnston Sfortunatamente non riesco a utilizzare nulla di diverso dai comandi interni o esterni standard per cmd.exe. – networkcode
VBScript e JScript sono utilità native standard disponibili per CMD.EXE, con un buon supporto di espressioni regolari. PowerShell è nativo da Vista in poi, e ha anche un buon supporto per le espressioni regolari. – dbenham