استخراج خطوط محددة (بناء على رقم السطر) باستخدام ملف دفعي

StackOverflow https://stackoverflow.com//questions/25036020

سؤال

أحتاج إلى استخراج أسطر محددة من ملف نصي (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]

الكود الأول - 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

الكود الثاني - 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')؟

هل كانت مفيدة؟

المحلول

لك 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 بند

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top