คุณวนรอบแต่ละบรรทัดในไฟล์ข้อความโดยใช้ไฟล์แบตช์ windows ได้อย่างไร


244

ฉันต้องการทราบวิธีวนรอบแต่ละบรรทัดในไฟล์ข้อความโดยใช้ไฟล์แบตช์ Windows และประมวลผลแต่ละบรรทัดอย่างต่อเนื่อง

คำตอบ:


304

โพสต์ด้านล่างช่วยได้มาก แต่ไม่ได้ทำในสิ่งที่ฉันระบุไว้ในคำถามที่ฉันต้องการประมวลผลทั้งบรรทัดโดยรวม นี่คือสิ่งที่ฉันพบว่าทำงาน

for /F "tokens=*" %%A in (myfile.txt) do [process] %%A

คำหลักโทเค็นที่มีเครื่องหมายดอกจัน (*) จะดึงข้อความทั้งหมดสำหรับทั้งบรรทัด หากคุณไม่ใส่เครื่องหมายดอกจันระบบจะดึงเฉพาะคำแรกบนบรรทัด ฉันคิดว่ามันเกี่ยวข้องกับช่องว่าง

สำหรับ Command บน TechNet

ฉันขอขอบคุณโพสต์ทั้งหมด!


usebackqหากมีช่องว่างในเส้นทางไฟล์ของคุณคุณจะต้องใช้ ตัวอย่างเช่น.

for /F "usebackq tokens=*" %%A in ("my file.txt") do [process] %%A

37
การเพิ่มเล็กน้อย: เพื่อให้งานนี้จากบรรทัดคำสั่งแบบโต้ตอบแทน%%Aด้วย%Aในคำสั่งดังกล่าว %%A was unexpected at this time.มิฉะนั้นคุณจะได้รับ
vadipp

16
หากคุณต้องการคำสั่งหลายบรรทัดหลังจาก "DO" คุณสามารถใส่วงเล็บเปิด "(" และอีกไม่กี่บรรทัดในภายหลังให้ปิดด้วยวงเล็บ ")" - และคุณสามารถใส่รหัสของคุณได้ บล็อกภายในสิ่งเหล่านั้น (เยื้องกับรสนิยมของคุณ)
BrainSlugs83

3
ขอบคุณสำหรับรูปแบบที่ ฉันได้พบว่าฉันไม่สามารถใส่เครื่องหมายคำพูด ( ") รอบชื่อไฟล์ -. สำหรับชื่อไฟล์ที่มีช่องว่างเพียงแค่ให้ฉันชื่อไฟล์เช่นfor /F "tokens=*" %%A in ("myfile.txt") do echo A = %%A-> A = myfile.txtความคิดใดวิธีการขัดขวางนี้.
จะ

1
ตรวจสอบให้แน่ใจว่าไฟล์ที่คุณทำงานนั้นได้รับการเข้ารหัสใน ANSI หรือ UTF8 ฉันเกาหัวของฉันว่าทำไมสิ่งนี้ไม่ทำงานจนกว่าฉันจะลองดูไฟล์โดยใช้คำสั่ง TYPE และเอาท์พุทไม่ใช่สิ่งที่ฉันคาดหวัง ณ จุดนี้ฉันสังเกตเห็นว่าไฟล์ถูกเข้ารหัสใน "UCS-2 BE BOM" ด้วยเหตุผลบางอย่าง!
Dan Stevens

1
เป็นค่าที่ชี้ให้เห็นว่าพารามิเตอร์ดัชนีในลูปของคุณต้องเป็นอักขระตัวเดียว ตัวอย่างเช่น %% i นั้นใช้ได้ แต่ดัชนี %% จะล้มเหลว
Vincent

59

จากการอ้างอิงบรรทัดคำสั่ง Windows:

ในการแยกวิเคราะห์ไฟล์โดยไม่สนใจบรรทัดที่คอมเม้นต์ให้พิมพ์:

for /F "eol=; tokens=2,3* delims=," %i in (myfile.txt) do @echo %i %j %k

คำสั่งนี้วิเคราะห์คำแต่ละบรรทัดใน Myfile.txt โดยไม่สนใจบรรทัดที่ขึ้นต้นด้วยเครื่องหมายอัฒภาคและส่งโทเค็นที่สองและสามจากแต่ละบรรทัดไปยัง FOR body (โทเค็นถูกคั่นด้วยเครื่องหมายจุลภาคหรือช่องว่าง) เนื้อความของคำสั่ง FOR อ้างอิง% i เพื่อรับโทเค็นที่สอง,% j เพื่อรับโทเค็นที่สามและ% k เพื่อรับโทเค็นที่เหลือทั้งหมด

หากชื่อไฟล์ที่คุณระบุมีช่องว่างให้ใช้เครื่องหมายคำพูดล้อมรอบข้อความ (เช่น "ชื่อไฟล์") ในการใช้เครื่องหมายคำพูดคุณต้องใช้ usebackq มิฉะนั้นเครื่องหมายคำพูดจะถูกตีความว่าเป็นการกำหนดสตริงตัวอักษรที่จะแยกวิเคราะห์

อย่างไรก็ตามคุณสามารถค้นหาไฟล์วิธีใช้บรรทัดคำสั่งบนระบบ Windows ส่วนใหญ่ได้ที่:

 "C:\WINDOWS\Help\ntcmds.chm"

8
เพื่อชี้แจง"เพื่อใช้เครื่องหมายคำพูดคุณต้องใช้usebackq" : for /f "usebackq" %%a in ("Z:\My Path Contains Spaces\xyz\abc.txt")
drzaus

35

ในไฟล์แบทช์คุณต้องใช้%%แทน%: (Type help for)

for /F "tokens=1,2,3" %%i in (myfile.txt) do call :process %%i %%j %%k
goto thenextstep
:process
set VAR1=%1
set VAR2=%2
set VAR3=%3
COMMANDS TO PROCESS INFORMATION
goto :EOF

สิ่งนี้จะทำอะไร: กระบวนการ "do call: process %% i %% j %% k" ที่ส่วนท้ายของคำสั่ง for ส่งผ่านข้อมูลที่ได้รับในคำสั่ง for จาก myfile.txt ไปยังรูทีนย่อย "process" '

เมื่อคุณใช้คำสั่ง for ในโปรแกรมแบทช์คุณต้องใช้เครื่องหมาย% คู่สำหรับตัวแปร

บรรทัดต่อไปนี้ส่งผ่านตัวแปรเหล่านั้นจากคำสั่ง for ถึงกระบวนการ 'รูทีนย่อย' และอนุญาตให้คุณประมวลผลข้อมูลนี้

set VAR1=%1
 set VAR2=%2
 set VAR3=%3

ฉันมีการใช้งานที่ล้ำสมัยของการตั้งค่าที่แน่นอนนี้ซึ่งฉันยินดีที่จะแบ่งปันหากต้องการตัวอย่างเพิ่มเติม เพิ่มใน EOL หรือ Delims ของคุณตามที่ต้องการแน่นอน


27

การปรับปรุงคำตอบ "FOR / F .. " ครั้งแรก: สิ่งที่ฉันต้องทำคือเรียกใช้งานสคริปต์ทุกรายการใน MyList.txt ดังนั้นจึงใช้งานได้สำหรับฉัน:

for /F "tokens=*" %A in  (MyList.txt) do CALL %A ARG1

- หรือหากคุณต้องการทำหลายบรรทัด:

for /F "tokens=*" %A in  (MuList.txt) do (
ECHO Processing %A....
CALL %A ARG1
)

แก้ไข: ตัวอย่างที่ระบุข้างต้นสำหรับการดำเนินการ FOR วนจาก command-prompt; จากชุดสคริปต์ต้องเพิ่ม% พิเศษดังที่แสดงด้านล่าง:

---START of MyScript.bat---
@echo off
for /F "tokens=*" %%A in  ( MyList.TXT) do  (
   ECHO Processing %%A.... 
   CALL %%A ARG1 
)
@echo on
;---END of MyScript.bat---

21

@ คำตอบ MrKraus เป็นคำแนะนำ เพิ่มเติมให้ฉันเพิ่มว่าถ้าคุณต้องการโหลดไฟล์ที่อยู่ในไดเรกทอรีเดียวกันกับไฟล์แบตช์คำนำหน้าชื่อไฟล์ด้วย% ~ dp0 นี่คือตัวอย่าง:

cd /d %~dp0
for /F "tokens=*" %%A in (myfile.txt) do [process] %%A

หมายเหตุ:หากชื่อไฟล์หรือไดเรกทอรีของคุณ (เช่น myfile.txt ในตัวอย่างด้านบน) มีช่องว่าง (เช่น 'my file.txt' หรือ 'c: \ Program Files') ให้ใช้:

for /F "tokens=*" %%A in ('type "my file.txt"') do [process] %%A

ด้วยคีย์เวิร์ดtype ที่เรียกใช้typeโปรแกรมซึ่งแสดงเนื้อหาของไฟล์ข้อความ หากคุณไม่ต้องการประสบกับค่าใช้จ่ายในการเรียกคำสั่ง type คุณควรเปลี่ยนไดเรกทอรีเป็นไดเรกทอรีของไฟล์ข้อความ โปรดทราบว่าประเภทนั้นยังจำเป็นสำหรับชื่อไฟล์ที่มีช่องว่าง

ฉันหวังว่านี่จะช่วยให้ใครบางคน!


ไม่จำเป็นต้องใส่คำนำหน้าชื่อไฟล์เป็นชุดไฟล์จะค้นหาในโฟลเดอร์ปัจจุบันตามค่าเริ่มต้น
foxidrive

1
@foxidrive: โอเคฉันได้ยินคุณ แม้ว่าจะต้องระมัดระวัง ตัวอย่างเช่นหากมีการเปลี่ยนแปลงไดเรกทอรีมันจะดูในไดเรกทอรีนั้นมากกว่าหนึ่งไฟล์แบทช์ที่อยู่ในนั้นการแก้ปัญหาจะถูกเรียก**cd /d %~dp0**ก่อน for for loop สิ่งนี้จะทำให้แน่ใจว่าคุณกำลังอ้างอิงไฟล์ในไดเรกทอรีที่มีไฟล์แบตช์อยู่ขอบคุณที่สังเกต
Marvin Thobejane

2
ขอบคุณและ +1 สำหรับtypewalkaround
halex

ฉันไม่สามารถหลีกเลี่ยงการtypeทำงานได้ฉันต้องอ้างชื่อไฟล์ของฉันเพราะมันอยู่ในไดเรกทอรีอื่นที่มีการเว้นวรรค (ประณามคุณProgram Files) ฉันได้รับข้อผิดพลาดThe system cannot find the file `type.
scragar

1
@scarar คุณมีใบเสนอราคาที่ถูกต้องหรือไม่? มันต้องเป็น 'ไม่' บนแป้นพิมพ์ของฉันมันเป็นรหัสเดียวกับ @
FrinkTheBrave

18

คำตอบที่ยอมรับนั้นดี แต่มีข้อ จำกัด สองประการ
มันจะปล่อยบรรทัดว่างและบรรทัดที่ขึ้นต้นด้วย;

หากต้องการอ่านบรรทัดของเนื้อหาใด ๆ คุณต้องมีการสลับเทคนิคการขยายการเลื่อน

@echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ text.txt"`) do (
    set "var=%%a"
    SETLOCAL EnableDelayedExpansion
    set "var=!var:*:=!"
    echo(!var!
    ENDLOCAL
)

Findstr ใช้เพื่อนำหน้าแต่ละบรรทัดด้วยหมายเลขบรรทัดและโคลอนดังนั้นบรรทัดว่างจะไม่ว่างเปล่าอีกต่อไป

DelayedExpansion จำเป็นต้องปิดการใช้งานเมื่อเข้าถึง%%aพารามิเตอร์เครื่องหมายอัศเจรีย์!และเครื่องหมายอื่น^จะหายไปเนื่องจากมีความหมายพิเศษในโหมดนั้น

แต่หากต้องการลบหมายเลขบรรทัดออกจากบรรทัดจำเป็นต้องเปิดใช้งานส่วนขยายที่ล่าช้า
set "var=!var:*:=!"ลบทั้งหมดจนถึงโคลอนแรก (การใช้delims=:จะลบโคลอนทั้งหมดที่จุดเริ่มต้นของบรรทัดด้วยไม่ใช่เฉพาะโคลอนจาก findstr)
endlocal ปิดใช้งานการขยายตัวที่ล่าช้าอีกครั้งสำหรับบรรทัดถัดไป

ขณะนี้ข้อ จำกัด เพียงอย่างเดียวคือขีดจำกัดความยาวบรรทัดที่ ~ 8191 แต่ดูเหมือนว่าจะไม่มีทางเอาชนะได้


Win 10 ไม่อนุญาตให้ใช้setlocalกับ commandline เมื่อฉันเรียกใช้รหัสใน CMD ฉันจะได้รับ! var! แทนช่องว่าง จะแก้ไขอย่างไร
Zimba

ขีดจำกัดความยาวบรรทัดสามารถแก้ไขได้โดยการแยกไฟล์ไปยังไฟล์ temp ที่มีความยาวสูงสุดของสาย 8190 ก่อนประมวลผล รวมกันอีกหนึ่งไฟล์
Zimba

14

หรือคุณอาจยกเว้นตัวเลือกในเครื่องหมายคำพูด:

FOR /F %%i IN (myfile.txt) DO ECHO %%i

1
เครื่องหมายสองเปอร์เซ็นต์ที่อยู่ติดกัน %% จะถือว่าเป็นเครื่องหมายเปอร์เซ็นต์เดียวในคำสั่ง (ไม่ใช่ไฟล์แบตช์)
พอล

9

นี่คือไฟล์ bat ที่ฉันเขียนเพื่อรันสคริปต์ SQL ทั้งหมดในโฟลเดอร์:

REM ******************************************************************
REM Runs all *.sql scripts sorted by filename in the current folder.
REM To use integrated auth change -U <user> -P <password> to -E
REM ******************************************************************

dir /B /O:n *.sql > RunSqlScripts.tmp
for /F %%A in (RunSqlScripts.tmp) do osql -S (local) -d DEFAULT_DATABASE_NAME -U USERNAME_GOES_HERE -P PASSWORD_GOES_HERE -i %%A
del RunSqlScripts.tmp


6

anwser ที่ยอมรับโดยใช้cmd.exeและ

for /F "tokens=*" %F in (file.txt) do whatever "%F" ...

ใช้งานได้กับไฟล์ "ปกติ" เท่านั้น มันล้มเหลวอย่างน่าสังเวชด้วยไฟล์ขนาดใหญ่

สำหรับไฟล์ขนาดใหญ่คุณอาจต้องใช้ Powershell และสิ่งนี้:

[IO.File]::ReadLines("file.txt") | ForEach-Object { whatever "$_" }

หรือถ้าคุณมีหน่วยความจำเพียงพอ:

foreach($line in [System.IO.File]::ReadLines("file.txt")) { whatever "$line" } 

สิ่งนี้ใช้ได้กับฉันด้วยไฟล์ 250 MB ที่มีมากกว่า 2 ล้านบรรทัดซึ่งfor /F ...คำสั่งติดค้างหลังจากสองสามพันบรรทัด

สำหรับความแตกต่างระหว่างforeachและForEach-Objectดูจะได้รู้ว่า ForEach และ ForEach

(เครดิต: อ่านไฟล์ทีละบรรทัดใน PowerShell )


1

ตัวอย่างดัดแปลงที่นี่เพื่อแสดงรายการแอพ Rails ของเราใน Heroku - ขอบคุณ!

cmd /C "heroku list > heroku_apps.txt"
find /v "=" heroku_apps.txt | find /v ".TXT" | findstr /r /v /c:"^$" > heroku_apps_list.txt
for /F "tokens=1" %%i in (heroku_apps_list.txt) do heroku run bundle show rails --app %%i

รหัสเต็มนี่


ตามความคิดเห็นต่อคำถามอื่นด้านบน - คุณสามารถข้ามการสร้าง / อ่านไฟล์และใช้งานได้for /f "tokens=1" %%i in ('find /v "=" heroku_apps.txt ^| find /v ".TXT" ^| findstr /r /v /c:"^$"') do...(โปรดสังเกตว่าการเพิ่มของ^เคยใช้เพื่อหลบหนีไปป์ดังนั้นมันจะถูกส่งผ่านไปยังforโปรเซสเซอร์โดยตรงและไม่ได้โดยตรง)
user66001

0

หากต้องการพิมพ์บรรทัดทั้งหมดในไฟล์ข้อความจากบรรทัดคำสั่ง (ที่มีExpansionล่าช้า):

set input="path/to/file.txt"

for /f "tokens=* delims=[" %i in ('type "%input%" ^| find /v /n ""') do (
set a=%i
set a=!a:*]=]!
echo:!a:~1!)

ทำงานร่วมกับช่องว่างนำหน้าบรรทัดว่างบรรทัดว่าง

ทดสอบกับ Win 10 CMD


ลองพระเจ้า แต่ตัวอย่างแรกของคุณลบชั้นนำ]]]จากบรรทัดตัวอย่างที่สองจะปล่อยบรรทัดว่างและบรรทัดที่ขึ้นต้นด้วย space
jeb

อันที่สองหมายถึงการลบบรรทัดว่าง delimsบรรทัดแรกสามารถแก้ไขได้หากบรรทัดใด ๆ ในไฟล์ข้อความเริ่มต้นด้วย]เช่น แทนที่ด้วยอักขระบางตัวที่ไม่ได้หรือตัวควบคุมเช่น backspace หรือเบลล์; โดยปกติจะไม่พบในไฟล์ข้อความ เหตุผลdelims=]คือการเอาตัวยึดที่สร้างขึ้นโดย/nในfindคำสั่งเพื่อรักษาบรรทัดว่าง
Zimba

@jeb: วงเล็บ]]] แก้ไขปัญหาแล้ว ดูการอัพเดตเพื่อพิมพ์บรรทัดทั้งหมดในไฟล์ข้อความ ทำงานบน Win 10 CMD ด้วย
Zimba
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.