批处理文件 - 如何将 FindStr 与百分比一起使用
Batch file - How to use FindStr with percent
我有一个包含以下内容的批处理文件 header:
@Echo off
SETLOCAL EnableDelayedExpansion EnableExtensions
在括号 ()
中的 If
语句中,我有以下代码:
Echo SOME_VAR|FindStr /r /C:"^.*SOME.*$"
Echo Error: !errorlevel!
Echo %%SOME_VAR%%|FindStr /r /C:"^.*SOME.*$"
Echo Error: !errorlevel!
这将打印:
SOME_VAR
Error: 0
Error: 1
如果SOME_VAR是一个现有的环境变量,这就是我得到的。如果我删除变量,我会得到预期的成功。
这里发生了什么?我还需要逃避什么吗?如果变量存在,我怎样才能在第二个上成功找到?我只对搜索文本包含 %
字符并且恰好与现有变量名称匹配的文本搜索感兴趣。
顺便说一句,用于比较的源最终也将是一个变量,我已经在其中加载了从 Windows 注册表中读取的 PATH。所以最终,我要搜索的字符串将变成 /C:"^.%%SOME_VAR%%;.*$"
我的 PATH 变量如下所示:
%SOME_VAR%;C:\Windows\system32...................etc
是的,还需要另一层转义,因为管道的每一侧都是通过 CMD /C
使用命令行上下文而不是批处理上下文执行的。初始批解析器将 %%SOME_VAR%%
转换为 %SOME_VAR%
。如果变量未定义,命令行解析器将保持 %SOME_VAR%
不变。如果定义了变量,我们需要防止扩展。将百分比加倍在命令行上下文中不起作用。解决方案是在百分比之间的某处插入一个消失的插入符号,例如 %^SOME_VAR%
。插入符号被视为变量名称的一部分,因此它可以防止变量扩展(除非您有一个名为 ^SOME_VAR
的变量)。扩展失败后,插入符被正常的转义过程消耗掉。必须转义插入符号,以便批处理解析器将插入符号传递给 CMD /C
命令行上下文。
最终批处理行变为:
Echo %%^^SOME_VAR%% | FindStr SOME_VAR
注意:我将 FINDSTR 命令简化为更简单但等效的搜索。
当您修改右侧的搜索以包括百分比时,您还需要插入转义插入符号。
更新以回应评论中的问题
以下代码演示了一些使用变量的可能方法:
@echo off
setlocal disableDelayedExpansion
:: Put both the text you want to search, as well as the search itself, in variables
set "text=%%SOME_VAR%%;C:\Windows\system32...................etc"
set "search=%%SOME_VAR%%"
echo text=%text%
echo search=%search%
echo(
echo(
echo Starting with delayed expansion disabled
echo -----------------------------------------
echo(
:: Use delayed expansion to safely expand any variable without worrying about content.
:: Both sides of the pipe are executed in a command line context with delayed expansion disabled.
:: You must use CMD /V:ON to enable delayed expansion within the pipe.
echo Test when SOME_VAR is undefined:
set "SOME_VAR="
if 1==1 (
cmd /v:on /c echo !text!|cmd /v:on /c findstr "!search!"
)
echo(
echo Test when SOME_VAR is defined:
set "SOME_VAR=DEFINED"
if 1==1 (
cmd /v:on /c echo !text!|cmd /v:on /c findstr "!search!"
)
echo(
setlocal enableDelayedExpansion
echo(
echo(
echo Now try with delayed expansion enabled
echo -----------------------------------------
echo(
:: Even though delayed expansion is enabled within the batch script, it is still disabled
:: within the pipe, so we still have to explicitly enable it via CMD /V:ON.
:: But now we must prevent expansion of the variables while in the batch context.
:: You have two options:
:: 1) Escape the !. The escape syntax changes depending on whether it is inside quotes or not:
echo Escape test:
if 1==1 (
cmd /v:on /c echo ^^!text^^!|cmd /v:on /c findstr "^!search^!"
)
echo(
:: 2) Enclose both sides of the pipe within parentheses (very weird, but it works)
echo Parentheses test:
if 1==1 (
(cmd /v:on /c echo !text!)|(cmd /v:on /c findstr "!search!")
)
--输出--
text=%SOME_VAR%;C:\Windows\system32...................etc
search=%SOME_VAR%
Starting with delayed expansion disabled
-----------------------------------------
Test when SOME_VAR is undefined:
%SOME_VAR%;C:\Windows\system32...................etc
Test when SOME_VAR is defined:
%SOME_VAR%;C:\Windows\system32...................etc
Now try with delayed expansion enabled
-----------------------------------------
Escape test:
%SOME_VAR%;C:\Windows\system32...................etc
Parentheses test:
%SOME_VAR%;C:\Windows\system32...................etc
我有一个包含以下内容的批处理文件 header:
@Echo off
SETLOCAL EnableDelayedExpansion EnableExtensions
在括号 ()
中的 If
语句中,我有以下代码:
Echo SOME_VAR|FindStr /r /C:"^.*SOME.*$"
Echo Error: !errorlevel!
Echo %%SOME_VAR%%|FindStr /r /C:"^.*SOME.*$"
Echo Error: !errorlevel!
这将打印:
SOME_VAR
Error: 0
Error: 1
如果SOME_VAR是一个现有的环境变量,这就是我得到的。如果我删除变量,我会得到预期的成功。
这里发生了什么?我还需要逃避什么吗?如果变量存在,我怎样才能在第二个上成功找到?我只对搜索文本包含 %
字符并且恰好与现有变量名称匹配的文本搜索感兴趣。
顺便说一句,用于比较的源最终也将是一个变量,我已经在其中加载了从 Windows 注册表中读取的 PATH。所以最终,我要搜索的字符串将变成 /C:"^.%%SOME_VAR%%;.*$"
我的 PATH 变量如下所示:
%SOME_VAR%;C:\Windows\system32...................etc
是的,还需要另一层转义,因为管道的每一侧都是通过 CMD /C
使用命令行上下文而不是批处理上下文执行的。初始批解析器将 %%SOME_VAR%%
转换为 %SOME_VAR%
。如果变量未定义,命令行解析器将保持 %SOME_VAR%
不变。如果定义了变量,我们需要防止扩展。将百分比加倍在命令行上下文中不起作用。解决方案是在百分比之间的某处插入一个消失的插入符号,例如 %^SOME_VAR%
。插入符号被视为变量名称的一部分,因此它可以防止变量扩展(除非您有一个名为 ^SOME_VAR
的变量)。扩展失败后,插入符被正常的转义过程消耗掉。必须转义插入符号,以便批处理解析器将插入符号传递给 CMD /C
命令行上下文。
最终批处理行变为:
Echo %%^^SOME_VAR%% | FindStr SOME_VAR
注意:我将 FINDSTR 命令简化为更简单但等效的搜索。
当您修改右侧的搜索以包括百分比时,您还需要插入转义插入符号。
更新以回应评论中的问题
以下代码演示了一些使用变量的可能方法:
@echo off
setlocal disableDelayedExpansion
:: Put both the text you want to search, as well as the search itself, in variables
set "text=%%SOME_VAR%%;C:\Windows\system32...................etc"
set "search=%%SOME_VAR%%"
echo text=%text%
echo search=%search%
echo(
echo(
echo Starting with delayed expansion disabled
echo -----------------------------------------
echo(
:: Use delayed expansion to safely expand any variable without worrying about content.
:: Both sides of the pipe are executed in a command line context with delayed expansion disabled.
:: You must use CMD /V:ON to enable delayed expansion within the pipe.
echo Test when SOME_VAR is undefined:
set "SOME_VAR="
if 1==1 (
cmd /v:on /c echo !text!|cmd /v:on /c findstr "!search!"
)
echo(
echo Test when SOME_VAR is defined:
set "SOME_VAR=DEFINED"
if 1==1 (
cmd /v:on /c echo !text!|cmd /v:on /c findstr "!search!"
)
echo(
setlocal enableDelayedExpansion
echo(
echo(
echo Now try with delayed expansion enabled
echo -----------------------------------------
echo(
:: Even though delayed expansion is enabled within the batch script, it is still disabled
:: within the pipe, so we still have to explicitly enable it via CMD /V:ON.
:: But now we must prevent expansion of the variables while in the batch context.
:: You have two options:
:: 1) Escape the !. The escape syntax changes depending on whether it is inside quotes or not:
echo Escape test:
if 1==1 (
cmd /v:on /c echo ^^!text^^!|cmd /v:on /c findstr "^!search^!"
)
echo(
:: 2) Enclose both sides of the pipe within parentheses (very weird, but it works)
echo Parentheses test:
if 1==1 (
(cmd /v:on /c echo !text!)|(cmd /v:on /c findstr "!search!")
)
--输出--
text=%SOME_VAR%;C:\Windows\system32...................etc
search=%SOME_VAR%
Starting with delayed expansion disabled
-----------------------------------------
Test when SOME_VAR is undefined:
%SOME_VAR%;C:\Windows\system32...................etc
Test when SOME_VAR is defined:
%SOME_VAR%;C:\Windows\system32...................etc
Now try with delayed expansion enabled
-----------------------------------------
Escape test:
%SOME_VAR%;C:\Windows\system32...................etc
Parentheses test:
%SOME_VAR%;C:\Windows\system32...................etc