Làm thế nào để bạn lặp qua từng dòng trong tệp văn bản bằng tệp bó windows?


244

Tôi muốn biết cách lặp qua từng dòng trong tệp văn bản bằng tệp bó Windows và xử lý từng dòng văn bản liên tiếp.

Câu trả lời:


304

Các bài viết dưới đây đã giúp rất nhiều, nhưng không làm những gì tôi đã nêu trong câu hỏi của tôi, nơi tôi cần xử lý toàn bộ dòng. Đây là những gì tôi tìm thấy để làm việc.

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

Từ khóa mã thông báo có dấu hoa thị (*) sẽ kéo tất cả văn bản cho toàn bộ dòng. Nếu bạn không đặt dấu hoa thị, nó sẽ chỉ kéo từ đầu tiên trên dòng. Tôi cho rằng nó phải làm với không gian.

Đối với Lệnh trên TechNet

Tôi đánh giá cao tất cả các bài viết!


Nếu có khoảng trắng trong đường dẫn tệp của bạn, bạn cần sử dụng usebackq. Ví dụ.

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

37
Một bổ sung nhỏ: để làm cho công việc này từ dòng lệnh tương tác, thay thế %%Abằng %Atrong lệnh trên. Nếu không, bạn sẽ nhận được %%A was unexpected at this time..
vadipp

16
FYI, nếu bạn cần thực hiện một lệnh nhiều dòng, sau "DO", bạn có thể đặt dấu ngoặc đơn mở "(" và một vài dòng sau, kết thúc nó bằng dấu ngoặc đơn đóng ")" - và bạn chỉ cần đặt mã của mình chặn bên trong những cái đó (thụt vào thị hiếu của bạn).
BrainSlugs83

3
Cảm ơn vì mô hình đó. Tôi đã thấy rằng tôi không thể đặt dấu ngoặc kép (") xung quanh tên tệp - Đối với tên tệp có khoảng trắng chỉ cho tôi tên tệp. Ví dụ for /F "tokens=*" %%A in ("myfile.txt") do echo A = %%A-> A = myfile.txt. Bạn có ý tưởng nào để ngăn chặn điều này không?
sẽ vào

1
Đảm bảo tệp bạn đang làm việc được mã hóa trong ANSI hoặc UTF8. Tôi đã gãi đầu về lý do tại sao điều này không hoạt động cho đến khi tôi thử xem tệp bằng lệnh TYPE và đầu ra không như tôi mong đợi. Tại thời điểm này, tôi nhận thấy tệp đã được mã hóa trong "UCS-2 BE BOM" vì một số lý do!
Dan Stevens

1
Thật đáng để chỉ ra rằng tham số chỉ mục trong vòng lặp của bạn phải là một ký tự đơn. Vì vậy, ví dụ %% i vẫn ổn nhưng chỉ số %% sẽ thất bại.
Vincent

59

Từ tham chiếu dòng lệnh Windows:

Để phân tích một tệp, bỏ qua các dòng nhận xét, gõ:

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

Lệnh này phân tích từng dòng trong Myfile.txt, bỏ qua các dòng bắt đầu bằng dấu chấm phẩy và chuyển mã thông báo thứ hai và thứ ba từ mỗi dòng sang phần thân FOR (mã thông báo được phân cách bằng dấu phẩy hoặc dấu cách). Phần thân của câu lệnh FOR tham chiếu% i để nhận mã thông báo thứ hai,% j để nhận mã thông báo thứ ba và% k để nhận tất cả các mã thông báo còn lại.

Nếu tên tệp mà bạn cung cấp chứa khoảng trắng, hãy sử dụng dấu ngoặc kép quanh văn bản (ví dụ: "Tên tệp"). Để sử dụng dấu ngoặc kép, bạn phải sử dụng usBackq. Mặt khác, dấu ngoặc kép được hiểu là xác định một chuỗi ký tự để phân tích cú pháp.

Nhân tiện, bạn có thể tìm thấy tệp trợ giúp dòng lệnh trên hầu hết các hệ thống Windows tại:

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

8
để làm rõ các "sử dụng dấu ngoặc kép, bạn phải sử dụng usebackq" : for /f "usebackq" %%a in ("Z:\My Path Contains Spaces\xyz\abc.txt")
drzaus

35

Trong tệp Batch bạn PHẢI sử dụng %%thay vì %: (Loại 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

Cái này làm gì: "do call: process %% i %% j %% k" ở cuối lệnh for chuyển thông tin thu được trong lệnh for từ myfile.txt sang "process" 'chương trình con'.

Khi bạn đang sử dụng lệnh for trong một chương trình bó, bạn cần sử dụng dấu% cho các biến.

Các dòng sau chuyển các biến đó từ lệnh for sang quy trình 'thường trình con' và cho phép bạn xử lý thông tin này.

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

Tôi có một số cách sử dụng khá tiên tiến của thiết lập chính xác này mà tôi sẽ sẵn sàng chia sẻ nếu cần thêm ví dụ. Thêm vào EOL hoặc Delims của bạn khi cần thiết tất nhiên.


27

Cải thiện câu trả lời "FOR / F .." đầu tiên: Điều tôi phải làm là gọi thực thi mọi tập lệnh được liệt kê trong MyList.txt, vì vậy nó hoạt động với tôi:

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

--OR, nếu bạn muốn làm điều đó qua nhiều dòng:

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

Chỉnh sửa: Ví dụ đưa ra ở trên là để thực hiện vòng lặp FOR từ dấu nhắc lệnh; từ tập lệnh bó, cần thêm%%, như hiển thị bên dưới:

---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

Câu trả lời của @ MrKraus mang tính hướng dẫn. Hơn nữa, hãy để tôi thêm rằng nếu bạn muốn tải một tệp nằm trong cùng thư mục với tệp bó, hãy đặt tiền tố tên tệp với% ~ dp0. Đây là một ví dụ:

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

NB :: Nếu tên tệp hoặc thư mục của bạn (ví dụ: myfile.txt trong ví dụ trên) có khoảng trắng (ví dụ: 'my file.txt' hoặc 'c: \ Program Files'), hãy sử dụng:

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

, Với các loại từ khóa gọi typechương trình, hiển thị các nội dung của một tập tin văn bản. Nếu bạn không muốn chịu chi phí gọi lệnh loại, bạn nên thay đổi thư mục thành thư mục của tệp văn bản. Lưu ý rằng loại vẫn được yêu cầu cho tên tệp có khoảng trắng.

Tôi hi vọng điêu nay se giup được ai đo!


Không cần phải thêm tiền tố vào tên tệp vì tệp bó sẽ tìm trong thư mục hiện tại theo mặc định.
foxidrive

1
@foxidrive: Được rồi, tôi nghe bạn. Mặc dù cần cẩn thận. Ví dụ: nếu một thư mục đã được thay đổi, nó sẽ tìm trong thư mục đó chứ không phải là một tệp bó. Trong đó giải pháp sẽ được gọi **cd /d %~dp0**trước vòng lặp for. Điều này sẽ đảm bảo rằng bạn đang tham chiếu một tệp trong thư mục chứa tệp bó. Cảm ơn bạn đã quan sát
Marvin Thobejane

2
Thx và +1 cho typewalkaround
halex

Tôi không thể typelàm việc xung quanh để làm việc, tôi đã phải trích dẫn tên tệp của mình vì nó nằm trong một thư mục khác có chứa khoảng trắng (Chết tiệt bạn Program Files). Tôi đang gặp lỗiThe system cannot find the file `type.
scragar

1
@scragar, bạn đã có trích dẫn đúng chưa? nó cần phải là một 'không phải là một `. Trên bàn phím của tôi, nó nằm trên cùng một phím với @
FrinkTheBrave

18

Câu trả lời được chấp nhận là tốt, nhưng có hai hạn chế.
Nó bỏ dòng trống và dòng bắt đầu bằng;

Để đọc các dòng của bất kỳ nội dung nào, bạn cần mở rộng kỹ thuật chuyển đổi bị trì hoãn.

@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 được sử dụng để tiền tố mỗi dòng có số dòng và dấu hai chấm, vì vậy các dòng trống không còn trống nữa.

DelayedExpansion cần phải bị vô hiệu hóa, khi truy cập %%atham số, các dấu chấm than khác !và dấu mũ ^sẽ bị mất, vì chúng có ý nghĩa đặc biệt trong chế độ đó.

Nhưng để xóa số dòng khỏi dòng, việc mở rộng bị trì hoãn cần phải được bật.
set "var=!var:*:=!"loại bỏ tất cả lên đến dấu hai chấm đầu tiên (sử dụng delims=:sẽ loại bỏ tất cả các dấu hai chấm ở đầu một dòng, không chỉ một từ tìm kiếm).
Endlocal vô hiệu hóa việc mở rộng bị trì hoãn một lần nữa cho dòng tiếp theo.

Giới hạn duy nhất bây giờ là giới hạn độ dài dòng ~ 8191, nhưng dường như không có cách nào để khắc phục điều này.


Win 10 không cho phép setlocaltrên dòng lệnh. Khi tôi chạy mã trên CMD, tôi nhận được! Var! thay vì khoảng trống. Làm thế nào để khắc phục?
Zimba

giới hạn độ dài dòng có thể được khắc phục bằng cách chia tệp thành tệp tạm thời có độ dài dòng tối đa 8190 trước khi xử lý. Sau đó kết hợp lại thành một tập tin.
Zimba

14

Hoặc, bạn có thể loại trừ các tùy chọn trong dấu ngoặc kép:

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

1
Hai dấu phần trăm cạnh nhau %% được coi như một dấu phần trăm duy nhất trong một lệnh (không phải là tệp bó).
Paul

9

Đây là một tập tin bat tôi đã viết để thực thi tất cả các tập lệnh SQL trong một thư mục:

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 được chấp nhận sử dụng cmd.exe

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

chỉ hoạt động cho các tập tin "bình thường". Nó thất bại thảm hại với các tập tin lớn.

Đối với các tệp lớn, bạn có thể cần sử dụng Powershell và đại loại như thế này:

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

hoặc nếu bạn có đủ bộ nhớ:

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

Điều này làm việc với tôi với một tệp 250 MB chứa hơn 2 triệu dòng, trong đó for /F ...lệnh bị kẹt sau vài nghìn dòng.

Để biết sự khác biệt giữa foreachForEach-Object, hãy xem Tìm hiểu về ForEach và ForEach-Object .

(tín dụng: Đọc từng dòng tệp trong PowerShell )


1

Các ví dụ được sửa đổi ở đây để liệt kê các ứng dụng Rails của chúng tôi trên Heroku - cảm ơn!

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

Mã đầy đủ ở đây .


Mỗi bình luận cho một câu hỏi khác ở trên - Bạn có thể bỏ qua việc tạo / đọc tệp và chỉ sử dụng for /f "tokens=1" %%i in ('find /v "=" heroku_apps.txt ^| find /v ".TXT" ^| findstr /r /v /c:"^$"') do...(Lưu ý việc thêm từ ^được sử dụng để thoát khỏi đường ống, để nó được chuyển đến forvà không trực tiếp đến bộ xử lý lệnh)
user66001

0

Để in tất cả các dòng trong tệp văn bản từ dòng lệnh (với delayExpansion):

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!)

Hoạt động với khoảng trắng hàng đầu, dòng trống, dòng khoảng trắng.

Đã thử nghiệm trên Win 10 CMD


Chúa thử, nhưng mẫu đầu tiên của bạn loại bỏ hàng đầu ]]]khỏi các dòng, mẫu thứ hai bỏ các dòng trống và dòng bắt đầu bằng khoảng trắng
jeb

Cái thứ 2 có nghĩa là loại bỏ các dòng trống. Người đầu tiên có thể sửa đổi delimsnếu bất kỳ dòng nào trong tệp văn bản bắt đầu bằng ]vd. thay thế bằng một số ký tự không hoặc ký tự điều khiển như backspace hoặc chuông; chúng thường không được tìm thấy trong các tập tin văn bản. Lý do delims=]là để loại bỏ placeholders tạo ra bởi /ncác findlệnh để duy trì dòng trống.
Zimba

@jeb: ngoặc]]] đã sửa lỗi. Xem cập nhật, để in tất cả các dòng trong tệp văn bản. Hoạt động trên Win 10 CMD cũng vậy.
Zimba
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.