混合 FOR 和 FINDSTR 时可笑的插入符号转义序列

Ridiculous caret escape sequence when mixing FOR and FINDSTR

我有一个字符串验证批处理,可以使用 FINDSTR 处理基本的正则表达式,今天我 认为 无法正确转义插入符号时几乎要退出了字符直到我添加了十几个^.

失败验证命令:stringVerifier.bat "Derpy QFail" "^^^^^^^^^^^^^^^^QFail" /R

通过验证命令:stringVerifier.bat "QFail Derpy" "^^^^^^^^^^^^^^^^QFail" /R

stringVerifier.bat

@echo off

REM ===== Verify Sub-String In String Script =====
REM It uses Window's native findstr.exe commandline application with simplified options and scope for checking strings instead of file strings.
REM Call this script by preceeding the commandline call with the word `call` instead of directly running it.
REM 
REM Parameter 1 is the string to search through. This must be wrapped in double-quotes.
REM Parameter 2 is the search pattern, e.g., "^QWARN". This must be wrapped in double-quotes.
REM Parameter 3 should be either /R for Regular Expression search or /L for a string-literal search.
REM Parameter 4 is optional. It should be true/false or t/f for case-sensitive searches.
REM Parameter 4 behavior will default to false for case-sensitivity if left out of the commandline parameters when called.
REM 
REM You can check success by exit code or if the value of %match_was_found% is true/false or if %match_found% isn't empty.
REM A false value for %match_was_found% means there's no result to check due to no match occurring.
REM A non-empty value for %match_found% always indicates success, and vice-versa.
REM These values reset every time you run this script.


REM Extract between 1 from the front and 1 from the end to strip commandline quotes
Set string_to_search=%1
Set string_to_search=%string_to_search:~1,-1%
Set search_pattern=%2
Set search_pattern=%search_pattern:~1,-1%


Set search_type=%3
Set case_sensitive=%4
IF /i "%case_sensitive%"=="t" Set case_sensitive=true
IF /i "%case_sensitive%"=="f" Set case_sensitive=false
IF /i "%case_sensitive%"=="" Set case_sensitive=false


IF "%string_to_search%"=="" echo You forgot to provide parameter one, %string_to_search%, to specify your string to search, e.g., "Start of line of this string"&&exit /b 1
IF "%search_pattern%"=="" echo You forgot to provide parameter two, %search_pattern%, to specify your search pattern, e.g., "^Start of.*string$"&&exit /b 1
IF "%search_type%"=="" echo You forgot to provide parameter three, %search_type%, to specify your search type, e.g., /R or /L&&exit /b 1
IF /i NOT "%search_type%"=="/R" IF NOT "%search_type%"=="/L" echo You didn't provide the correct third parameter, %search_type%, for /R or /L&&exit /b 1
IF /i NOT "%case_sensitive%"=="" IF NOT "%case_sensitive%"=="true" IF NOT "%case_sensitive%"=="false" echo You didn't provide the correct fourth, %case_sensitive%, parameter for true or false&&exit /b 1


Set match_was_found=
Set match_found=
Set Command_To_Run=
Set Command_Ender=


Set Command_To_Run=echo.%string_to_search%


IF NOT "%case_sensitive%"=="" IF NOT "%case_sensitive%"=="true" Set Command_Ender=/I
IF "%search_type%"=="/R" (Set Command_Ender=%Command_Ender% /R %search_pattern%) ELSE (Set Command_Ender=%Command_Ender% /C:%search_pattern%)


FOR /F "tokens=*" %%i IN (' %Command_To_Run% ^| findstr.exe %Command_Ender% ') DO Set match_found=%%i


REM Deleting all variables we don't want retained as temporary env vars.
IF "%match_found%"=="" Set match_was_found=false&&Set string_to_search=&&Set search_pattern=&&Set search_type=&&Set Command_To_Run=&&Set Command_Ender=&&Set case_sensitive=&&exit /b 1
IF NOT "%match_found%"=="" Set match_was_found=true&&Set string_to_search=&&Set search_pattern=&&Set search_type=&&Set Command_To_Run=&&Set Command_Ender=&&Set case_sensitive=


REM Comment out this line or add more script logic if you want to disable console output of the matching line
echo %match_found%
exit /b 0

有什么方法可以在批处理本身中绕过这个荒谬的转义序列,而无需生成临时文件和其他类似的转义正则表达式元字符的烦恼?

您使用的 set variable 语法不正确。
由于没有引号,插入符号将用于任何 SET 命令以转义下一个字符。

这一行将占用你一半的插入符

Set search_pattern=%search_pattern:~1,-1%

您应该使用扩展集语法:

set "variable=content"

但是您只需要更改一些行即可将插入符号的总数减少到两个。

Set "search_pattern=%~2"  This takes the argument and removes also the quotes
...
IF "%search_type%"=="/R" (Set "Command_Ender=%Command_Ender% /R %search_pattern%") ELSE (Set "Command_Ender=%Command_Ender% /C:%search_pattern%")
...
FOR /F "tokens=*" %%i IN (' %Command_To_Run% ^| findstr.exe %%Command_Ender%% ') DO Set match_found=%%i

现在你只需要使用

stringVerifier.bat "QFail Derpy" "^^QFail" /R

那是因为最后一个 findstr 仍然消耗了一次插入符号。
这也可以用引号来改变,但是你必须改变你的 Command_Ender 变量来只保存选项,而不是搜索字符串。

要检查代码,您应该在某些地方使用 set Command_Enderset search_pattern 来显示变量的真实内容。
您还应该看看 delayed expansion,因为延迟扩展永远不会更改变量内容。