我必須檢查存儲在變量中的字符串的有效性,我不能使用外部CLI實用程序(grep,awk等),因此我選擇了FINDSTR。 該字符串格式(在正則表達式):在FINDSTR中使用子模式
([1-9][0-9]*:".*"(|".*")*)
我不知道如何檢查子模式(| 「*」)。 目前我的代碼是:
((ECHO.) | (SET /P "=(11:"a"|"b"|"c")") | (FINDSTR /R /C:"^([1-9][0-9]*:".*")$"))
問候。
我必須檢查存儲在變量中的字符串的有效性,我不能使用外部CLI實用程序(grep,awk等),因此我選擇了FINDSTR。 該字符串格式(在正則表達式):在FINDSTR中使用子模式
([1-9][0-9]*:".*"(|".*")*)
我不知道如何檢查子模式(| 「*」)。 目前我的代碼是:
((ECHO.) | (SET /P "=(11:"a"|"b"|"c")") | (FINDSTR /R /C:"^([1-9][0-9]*:".*")$"))
問候。
Mat M對於FINDSTR的限制是正確的。 FINDSTR正則表達式支持是非常原始的和非標準的。從命令行輸入HELP FINDSTR
或FINDSTR /?
以獲得所支持內容的簡要摘要。有關深入的解釋,請參閱What are the undocumented features and limitations of the Windows FINDSTR command?
我喜歡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
以下是運行批處理腳本
後的結果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
不錯,雖然我們不知道第六個測試用例是否真的是錯誤的。 –
@MatM - 好點。如果它應該是有效的,那麼解決方案將顯得更加複雜。 – dbenham
@dbenham:解決方案是正確的,謝謝!我想告訴你一個我批量進行的項目,以徵求你的意見,可能會引起共同興趣! – networkcode
據我所知,findstr是無法分組regexps,所以(|".*")*
是一個否定的。如果你知道你有多少塊有,你複製你這樣的代碼
FINDSTR /R /C:"^([1-9][0-9]*:\"..*\"|\"..*\"|\"..*\")$"
這樣一來,如果你確信塊的數量是恆定的,具有空的""
如果需要的話,那麼你可以檢查它。
表達式中的雙引號將被忽略,除非您在它們前加\。
..*
結構旨在代替.+
:一個或多個字符。
該字符串不能包含常數的子模式,變量號從第一個數字開始,然後是:。也許解決辦法是立即用FINDSTR驗證字符串,然後用FOR/F分析每個子模式的標記,如果內容和數字正確,你認爲如何? – networkcode
@ user1125183 - 這應該可行,但這很棘手。請參閱[我的答案](http://stackoverflow.com/a/12570555/1012053) – dbenham
如果可能的話,您最好使用vbscript或powershell。操縱包含特殊字符的字符串在Windows批處理文件中是非常困難的。 –
@Harry Johnston不幸的是我不能使用除了標準的內部或外部命令cmd.exe以外的任何東西。 – networkcode
VBScript和JScript是可用於CMD.EXE的標準本地實用程序,具有良好的正則表達式支持。 PowerShell本身就是從Vista開始的,同時也有很好的正則表達式支持。 – dbenham