我知道这是一个老问题,但对于有类似问题的人,这里有一些额外的信息...
Lee,你关于为什么在for循环之外"%%a"无法工作的推理是正确的。%a-z和%A-Z变量(在批处理文件中为%%a-z)是for循环的构造,不存在于它之外。
我想推荐一个替代解决方案,它匹配正确的行号(不会跳过空行),不需要延迟扩展、计数器或goto语句。看一下下面的代码:
@echo off
for /f "tokens=1* delims=:" %%a in ('findstr /n .* "c:\file_list.txt"') do if "%%a"=="%1" set line=%%b
echo.%line%
以下是导致我进行上述更改的原因。假设您有以下文件内容:
Some text on line 1
Blah blah blah
More text
我做的第一件事是将(c:\file_list.txt)更改为('findstr /n .* "c:\file_list.txt"')。
- 'findstr /n .* "PATH\FILENAME"'读取文件并在每一行开头添加行号('/n')('.*'是匹配任何字符的正则表达式,"0或多个")。由于现在每行开头都有行号(即使是空行),因此for循环不会跳过任何行。
现在,在for循环中,每一行都将如下所示:
1:Some text on line 1
2:Blah blah blah
3:More text
接下来,我们使用"tokens=1* delims=:"来分割行号和内容。
- 'tokens=1*'将第一个标记(存储在%%a中)设置为分隔符之前的所有内容,将第二个标记(存储在%%b中)设置为分隔符之后的所有内容。
- 'delims=:'将":"设置为用于分割字符串的分隔符字符。
现在,当我们循环遍历文件时,%%a将返回当前行号,%%b将返回该行的内容。
现在唯一要做的就是比较%1参数与%%a(而不是计数器变量),并使用%%b来存储当前行内容:if "%%a" == "%1" set line=%%b。
额外的好处是,由于上述代码消除了在for循环中读取计数器变量,因此'enabledelayedexpansion'不再必要。
编辑:将'echo %line%'更改为'echo.%line%'。现在,这将正确显示空白行,而不是"ECHO is off."。将'type c:\file_list.txt ^| findstr /n .*'更改为'findstr /n .* "c:\file_list.txt"',因为findstr命令已经可以直接读取文件了。
Jeb,我认为我已经解决了所有特殊字符问题。试一试:
for /f "tokens=*" %%a in ('findstr /n .* "c:\file_list.txt"') do (
set "FullLine=%%a"
for /f "tokens=1* delims=:" %%b in ("%%a") do (
setlocal enabledelayedexpansion
set "LineData=!FullLine:*:=!"
if "%%b" equ "%1" echo(!LineData!
endlocal
)
)
for /f
命令会跳过空行。这可能会在某些情况下导致计数错误。 - Joey