Извлечение определенных строк (на основе номера строки) с помощью командного файла

Мне нужно извлечь определенные строки из текстового файла (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]

1-й код - call.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

2-й код - 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

ВЫВОД - 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')?


person gbabu    schedule 30.07.2014    source источник


Ответы (1)


Ваш 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

person MC ND    schedule 30.07.2014
comment
Отлично, спасибо @MC ND за разъяснение обоих вопросов. С твоим решением для моей супп. вопрос, я мог бы хотя бы сократить задержку, пропустив строки над моим st_ln. - person gbabu; 30.07.2014