2017-07-07 59 views
2

這部分運行良好,直到文件名中有一個&符,在這種情況下,它完全崩潰了我的腳本。批處理:導致與findstr相關的問題

echo %filename% | findstr /i /b /c:"%name% (%year%)" 

我不能只是把文件名放在引號中,因爲我需要在開頭找到字符串。那麼我該怎麼做呢?

回答

4

用於命令行:

echo %file^name:^&=^^^&% | ... 

裏面一個批處理文件

echo %%filename:^&=^^^&%% | ... 

它是如何工作的?
由於管道會創建兩個新的cmd.exe實例,因此echo ...將被解析兩次。
訣竅是僅在第二次擴展中擴展文件名。
然後擴大並用^&替換&以避免&出現問題。
插入符號將用於逃避&符號,它本身將被刪除。
在第二次擴展中,解析器僅看到echo %filename:&=^&%

要強制擴展到第二個解析步驟,批處理文件的百分號必須加倍。
從命令行,這不起作用,但變量名中任何地方的簡單的插入符號工作。

替代解決方案:

echo "%filename%" | findstr /i /b /c:^"\"%filename% (%year%)\"" 

這增加了簡單地引用和使用還引用在搜索表達式

+0

逃逸,雙重轉義,迫使雙解析,延遲擴展......有時我仍然感到驚訝那項工作的確可以做... – Stephan

+0

謝謝! ..我首先學習stephan提到的所有事情。 (cmd/v:on/c「(echo!filename!)」)| – bricktop

2

另一種選擇是使用延遲擴展,這需要顯式cmd/v:on選項。

cmd /v:on /c "(echo !filename!)" | findstr /i /b /c:"%name% (%year%)" 

如果批處理腳本已啓用延遲擴展,然後繞過左邊括號是需要防止延遲擴展從父腳本內發生(見Why does delayed expansion fail when inside a piped block of code?。子進程仍將默認禁用延遲擴展,因此仍需要cmd /v:on /c ...

@echo off 
setlocal enableDelayedExpansion 
... 
(cmd /v:on /c "(echo !filename!)") | findstr /i /b /c:"%name% (%year%)" 

另一種方式來延緩擴張,直到子進程是爲了躲避擴張

@echo off 
setlocal enableDelayedExpansion 
... 
cmd /v:on /c "(echo ^!filename^!)" | findstr /i /b /c:"%name% (%year%)" 
+0

您忘記了必要的括號。 ...'。否則'filename =%path%'失敗 – jeb

+0

@jeb - 我假設批處理腳本中未啓用延遲擴展。但是,是的,如果該批次啓用了延遲擴展,則需要左側的外部括號。 – dbenham