Mat M は、FINDSTR の制限について正しいです。FINDSTR 正規表現のサポートは、非常に原始的で非標準です。コマンド ラインからHELP FINDSTR
orを入力すると、サポートされている内容の簡単な概要が表示されます。FINDSTR /?
詳細な説明については、Windows FINDSTR コマンドの文書化されていない機能と制限事項は何ですか? を参照してください。
Harry Johnston のコメントが気に入りました - VBScript または JavaScript を使用してソリューションを作成するのは非常に簡単です。それははるかに良い選択だと思います。
しかし、これはネイティブのバッチ ソリューションです。OPがMat Mの回答へのコメントで述べたサブパターンの数に関する追加のルールを組み込みました。
解決策は驚くほどトリッキーです。特殊文字は、ECHO 出力を FINDSTR にパイプするときに問題を引き起こす可能性があります。これは、パイプの動作が原因です。パイプの各側は、独自の CMD セッションで実行されます。特殊文字は、引用するか、2 回エスケープするか、遅延展開によってのみ公開する必要があります。遅延展開を使用!
することにしましたが、遅延展開が正しいタイミングで行われるようにするには、文字を 2 回エスケープする必要があります。
可変数のサブパターンを解析する最も簡単な方法は、区切り文字を改行に置き換え、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
バッチスクリプトを実行した後の結果は次のとおりです
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")
アップデート
遅延拡張の有効化をパイプの後まで延期することにより、: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