2015-05-28 46 views
3

我有下面的头一个批处理文件:批处理文件 - 如何使用FINDSTR有百分之

@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是现有的ENV铁器变数,这就是我得到的。如果我删除变量,我会获得预期的成功。

这里会发生什么?我需要更多地逃避什么吗?如果变量存在,我怎样才能在第二个找到成功的发现?我只对搜索文本包含%字符并恰好匹配现有变量名称进行文本搜索感兴趣。

顺便说一下,比较的来源最终也会是一个变量,其中我已经从Windows注册表中读取PATH。所以最终,我搜索的字符串将成为/C:"^.%%SOME_VAR%%;.*$"

我的PATH变量是这样的:

%SOME_VAR%;C:\Windows\system32...................etc 

回答

3

是的,有因为管道的每一侧通过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!") 
) 

--OUTPUT--

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 
+0

谢谢,这是一个非常清晰的解释和它的工作原理... 但是我怎样才能做到这一点,当它是一个变量我呼应,与一个值如%SOME_VAR%;'。我无法构建我正在搜索的字符串并为其添加插入符号。 – jeremfg

+0

@jeremfg - 查看我更新的答案。 – dbenham

+0

哇......我很惊讶你在这有多好!非常感谢! – jeremfg