我需要从文本文件(input.txt)中提取特定行。我已经找到了一个解决方案,但有一些说明,当它与setlocalenabledealyed expansion
一起使用时,它无法正常工作。以下是示例
我的 input.txt (numbered using findstr /n)
。在这个例子中,我需要提取行号27到39之间的行。在我的完整批处理文件中,这些值是从另一个模块调用的。
1:[root]
2:ASKEHPPTEQWEIRAZOKXL
...
...
...
27:[parent2/child2]
28:NJ35CG5D9DEYXKMQKBJX
29:ZAZRMGB2E0KAG85FSPI3
30:E9046AQL44LV1R79OT8E
31:8OPXV1QYCTQVK34JZ2KV
32:3E32PWHGX5RGTFUXI9GC
33:H7DTDDFQZVGETGL764YU
34:174UOQMW35BCIQJNR1P8
35:7B3V0E9QXFQOM3NF08CZ
36:QH6FZVMKKGHKF0J8PB5O
37:QCRC90QCWWGAHRWBVMUI
38:4QPVEJW75GFW8DUM1PGU
39:[parent2/child3]
...
...
...
3000:[end]
第一个代码 - calling.bat - 使用CALL
@echo OFF
set st_ln=27
set end_ln=39
for /f "tokens=1,2 delims=:" %%a in (input.txt) do call :extract "%%a" "%%b"
goto :eof
:extract
set "ln=%~1"
set "sid=%~2"
if %ln% LEQ %st_ln% goto :eof
if %ln% GEQ %end_ln% goto :eof
echo.%sid%
goto :eof
:eof
第二个代码 - local.bat 与setlocalenabledelayedexpansion
REM @echo OFF
set st_ln=27
set end_ln=39
SETLOCAL ENABLEDELAYEDEXPANSION
for /f "tokens=1,2 delims=:" %%a in (input.txt) do (
set "ln=%%a"
set "sid=%%b"
if !ln! LEQ !st_ln! goto :eof
if !ln! GEQ !end_ln! goto :eof
echo.!sid!
)
:eof
OUTPUT - Calling.bat 绝对正常。但是 local.bat 不会返回任何错误,但它只迭代for循环一次。 (我尝试用%st_ln%&%end_ln%替换!st_ln!&!end_ln!但仍然是同样的问题)为什么?我错过了什么?
C:\Temp>calling.bat
NJ35CG5D9DEYXKMQKBJX
ZAZRMGB2E0KAG85FSPI3
E9046AQL44LV1R79OT8E
8OPXV1QYCTQVK34JZ2KV
3E32PWHGX5RGTFUXI9GC
H7DTDDFQZVGETGL764YU
174UOQMW35BCIQJNR1P8
7B3V0E9QXFQOM3NF08CZ
QH6FZVMKKGHKF0J8PB5O
QCRC90QCWWGAHRWBVMUI
4QPVEJW75GFW8DUM1PGU
C:\Temp>local.bat
C:\Temp>REM @echo OFF
C:\Temp>set st_ln=27
C:\Temp>set end_ln=39
C:\Temp>SETLOCAL ENABLEDELAYEDEXPANSION
C:\Temp>for /F "tokens=1,2 delims=:" %a in (input.txt) do (
set "ln=%a"
set "sid=%b"
if !ln! LEQ !st_ln! goto :eof
if !ln! GEQ !end_ln! goto :eof
echo.!sid!
)
C:\Temp>(
set "ln=1"
set "sid=[root]"
if !ln! LEQ !st_ln! goto :eof
if !ln! GEQ !end_ln! goto :eof
echo.!sid!
)
C:\Temp>
正如我上面所说,我可以得到预期的结果,但只是想知道它是否可以增强。我想从输入文件中提取特定行(行可以是输入文件中的任何位置,行数可以是1到20),输入文件最多可以有3000行。目前在上面的代码中我使用for循环并检查每一行的行号,因此它将遍历for循环3000次,这可能会延迟输出。有没有其他方法可以避免这种情况并加快脚本速度(可能是findstr'range'搜索)?
答案 0 :(得分:2)
你的local.bat
不起作用,因为当第一行被重新编号时,编号为1,并且第27行开始,条件if !ln! LEQ !st_ln! goto :eof
被评估为真并执行了goto
命令,离开for
循环。
对于补充问题,您可以计算在文件开头需要跳过的行数,然后只处理直到到达结束行。由于循环内没有变量变化,因此不需要延迟扩展
set /a "skipLines=st_ln-1"
if %skipLines% gtr 0 (
set "skipLines=skip=%skipLines%"
) else (
set "skipLines="
)
for /f "%skipLines% tokens=1,2 delims=:" %%a in (input.txt
) do if %%a gtr %end_ln% ( goto :eof ) else (
echo(%%b
)
if %skiplines% gtr 0
测试是必要的,因为for /f
循环不允许skip=0
子句