2017-07-07 64 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