2015-05-28 47 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