Jak przechodzić przez każdą linię w pliku tekstowym za pomocą pliku wsadowego systemu Windows?

244

Chciałbym wiedzieć, jak zapętlać każdą linię w pliku tekstowym za pomocą pliku wsadowego systemu Windows i przetwarzać kolejno każdą linię tekstu.

Pan Kraus
źródło

Odpowiedzi:

304

Poniższe posty bardzo pomogły, ale nie zrobiły tego, co powiedziałem w moim pytaniu, gdzie muszę przetworzyć całą linię jako całość. Oto, co znalazłem do pracy.

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

Słowo kluczowe tokeny oznaczone gwiazdką (*) spowoduje wyciągnięcie całego tekstu z całej linii. Jeśli nie wstawisz gwiazdki, spowoduje to wyciągnięcie tylko pierwszego słowa z linii. Zakładam, że ma to związek ze spacjami.

Dla Command w TechNet

Doceniam wszystkie posty!


Jeśli na ścieżce pliku znajdują się spacje, musisz użyć usebackq. Na przykład.

for /F "usebackq tokens=*" %%A in ("my file.txt") do [process] %%A
Pan Kraus
źródło
37
Niewielkim dodatkiem: do tej pracy z wiersza polecenia interaktywnie, wymienić %%Aze %Aw powyższym poleceniu. W przeciwnym razie dostaniesz %%A was unexpected at this time..
vadipp
16
Do Twojej wiadomości, jeśli chcesz wykonać polecenie składające się z wielu wierszy, po „DO” możesz wstawić otwarty nawias ”(„ i kilka linii później zakończyć go nawiasiem zamkniętym ”)” - i możesz po prostu wstawić kod blokuj je (wg własnych upodobań).
BrainSlugs83
3
Dzięki za ten wzór. Przekonałem się, że nie mogę umieścić cudzysłów ( ") wokół nazwy pliku -. Nazwy plików ze spacjami po prostu daje mi nazwę pliku Eg for /F "tokens=*" %%A in ("myfile.txt") do echo A = %%A-> A = myfile.txtJakieś pomysły jak to udaremnić.?
będzie
1
Upewnij się, że plik, który pracujesz, jest zakodowany w ANSI lub UTF8. Zastanawiałem się, dlaczego to nie działa, dopóki nie spróbowałem wyświetlić pliku za pomocą polecenia TYPE, a dane wyjściowe nie były tym, czego się spodziewałem. W tym momencie zauważyłem, że plik został z jakiegoś powodu zakodowany w „UCS-2 BE BOM”!
Dan Stevens
1
Warto zauważyć, że parametr indeksu w pętli musi być pojedynczym znakiem. Na przykład %% i jest w porządku, ale indeks %% zawiedzie.
Vincent
59

Z odwołania do wiersza poleceń systemu Windows:

Aby przeanalizować plik, ignorując skomentowane linie, wpisz:

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

To polecenie analizuje każdą linię w Myfile.txt, ignorując linie rozpoczynające się średnikiem i przekazując drugi i trzeci token z każdej linii do treści FOR (tokeny są rozdzielane przecinkami lub spacjami). Treść instrukcji FOR odwołuje się do% i, aby uzyskać drugi token,% j, aby uzyskać trzeci token, i% k, aby uzyskać wszystkie pozostałe tokeny.

Jeśli podane nazwy plików zawierają spacje, użyj cudzysłowów wokół tekstu (na przykład „Nazwa pliku”). Aby użyć cudzysłowu, musisz użyć usebackq. W przeciwnym razie znaki cudzysłowu są interpretowane jako definiujące dosłowny ciąg do analizy.

Nawiasem mówiąc, plik pomocy wiersza polecenia można znaleźć w większości systemów Windows pod adresem:

 "C:\WINDOWS\Help\ntcmds.chm"
Popiół
źródło
8
do wyjaśnienia „by użyć cudzysłowu, należy użyć usebackq : for /f "usebackq" %%a in ("Z:\My Path Contains Spaces\xyz\abc.txt")
drzaus
35

W pliku wsadowym MUSISZ użyć %%zamiast %: (Typ 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

Co to robi: „do call: proces %% i %% j %% k” na końcu polecenia for przekazuje informacje uzyskane w poleceniu for z pliku myfile.txt do podprogramu „process”.

Kiedy używasz polecenia for w programie wsadowym, musisz użyć podwójnych znaków% dla zmiennych.

Poniższe wiersze przekazują te zmienne z polecenia for do podprogramu procesu i umożliwiają przetwarzanie tych informacji.

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

Mam kilka całkiem zaawansowanych zastosowań tej dokładnej konfiguracji, którą chętnie podzielę się, jeśli będą potrzebne dalsze przykłady. Oczywiście dodaj EOL lub Delims.

użytkownik332474
źródło
27

Poprawianie pierwszej odpowiedzi „FOR / F ..”: Musiałem wywołać wykonanie każdego skryptu wymienionego w MyList.txt, więc zadziałało dla mnie:

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

--LUB, jeśli chcesz to zrobić przez wiele linii:

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

Edycja: Powyższy przykład dotyczy wykonania pętli FOR z wiersza polecenia; ze skryptu wsadowego należy dodać dodatkowy%, jak pokazano poniżej:

---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---
Yogesh Mahajan
źródło
21

@ Odpowiedź MrKrausa jest pouczająca. Ponadto pozwól mi dodać, że jeśli chcesz załadować plik znajdujący się w tym samym katalogu, co plik wsadowy, poprzedź nazwę pliku za pomocą% ~ dp0. Oto przykład:

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

Uwaga: Jeśli nazwa lub katalog pliku (np. Mój plik.txt w powyższym przykładzie) ma spację (np. „Mój plik.txt” lub „c: \ Program Files”), użyj:

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

, ze słowem kluczowym type wywołującym typeprogram, który wyświetla zawartość pliku tekstowego. Jeśli nie chcesz ponosić nakładów związanych z wywoływaniem polecenia type, zmień katalog na katalog pliku tekstowego. Zauważ, że typ jest nadal wymagany dla nazw plików ze spacjami.

Mam nadzieję, że to komuś pomoże!

Marvin Thobejane
źródło
Nie ma potrzeby poprzedzać nazwy pliku, ponieważ plik wsadowy domyślnie będzie wyglądał w bieżącym folderze.
foxidrive
1
@foxidrive: Dobra, słyszę cię. Chociaż należy zachować ostrożność. Na przykład, jeśli katalog został zmieniony, wyglądałby on w tym katalogu, a nie w tym, w którym znajduje się plik wsadowy. Rozwiązanie wówczas dzwoniłoby **cd /d %~dp0**przed pętlą for. Zapewniłoby to odniesienie do pliku w katalogu, w którym znajduje się plik wsadowy. Dzięki za obserwację
Marvin Thobejane
2
Thx i +1 do typeWalkaround
Halex
Nie mogę typeobejść problemu, musiałem zacytować swoją nazwę pliku, ponieważ jest on w innym katalogu, który zawiera spacje (cholera Program Files). Dostaję błądThe system cannot find the file `type.
scragar
1
@scragar, masz prawidłową wycenę? to musi być „nie”. Na mojej klawiaturze jest to ten sam klawisz, co @
FrinkTheBrave
18

Przyjęta odpowiedź jest dobra, ale ma dwa ograniczenia.
Zrzuca puste linie i linie zaczynające się od;

Aby odczytać wiersze dowolnej treści, potrzebujesz techniki przełączania opóźnionego rozszerzenia.

@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 służy do poprzedzania każdej linii numerem linii i dwukropkiem, więc puste linie nie są już puste.

DelayedExpansion należy wyłączyć podczas uzyskiwania dostępu do %%aparametru, w przeciwnym razie wykrzykniki !i znaki ^zostaną utracone, ponieważ mają one specjalne znaczenie w tym trybie.

Ale aby usunąć numer linii z linii, należy włączyć opóźnione rozszerzenie.
set "var=!var:*:=!"usuwa wszystkie do pierwszego dwukropka (użycie delims=:spowoduje usunięcie wszystkich dwukropków na początku linii, nie tylko tego z findstr).
Endlocal ponownie wyłącza opóźnione rozwinięcie dla następnej linii.

Jedynym ograniczeniem jest teraz limit długości linii wynoszący ~ 8191, ale wydaje się, że nie ma sposobu na obejście tego.

jeb
źródło
Win 10 nie zezwala setlocalna polecenie. Kiedy uruchamiam kod na CMD, dostaję! Var! zamiast pustych miejsc. Jak naprawić?
Zimba
limit długości linii można pokonać, dzieląc plik na pliki tymczasowe o maksymalnej długości linii 8190 przed przetwarzaniem. Następnie ponownie łączy się w jeden plik.
Zimba
14

Lub możesz wykluczyć opcje w cudzysłowach:

FOR /F %%i IN (myfile.txt) DO ECHO %%i
Paweł
źródło
1
Dwa znaki procentu obok siebie %% są traktowane jak pojedynczy znak procentu w poleceniu (nie plik wsadowy).
Paul
9

Oto plik nietoperza, który napisałem, aby wykonać wszystkie skrypty SQL w folderze:

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

źródło
6

Akceptowana odpowiedź przy użyciu cmd.exei

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

działa tylko dla „normalnych” plików. Zawodzi żałośnie przy dużych plikach.

W przypadku dużych plików może być konieczne użycie programu Powershell i czegoś takiego:

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

lub jeśli masz wystarczającą ilość pamięci:

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

Działa to dla mnie z plikiem 250 MB zawierającym ponad 2 miliony linii, w którym for /F ...polecenie utknęło po kilku tysiącach linii.

Różnice między foreachi ForEach-Objectzobacz Poznanie ForEach i ForEach-Object .

(kredyty: Czytaj plik linia po linii w PowerShell )

mivk
źródło
1

Zmodyfikowane przykłady tutaj, aby wyświetlić listę naszych aplikacji Railsowych na Heroku - dzięki!

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

Pełny kod tutaj .

sendbity
źródło
Od komentarza do innego pytania powyżej - Możesz pominąć tworzenie / czytanie pliku i po prostu użyć for /f "tokens=1" %%i in ('find /v "=" heroku_apps.txt ^| find /v ".TXT" ^| findstr /r /v /c:"^$"') do...(Zwróć uwagę na dodanie ^for
znaku
0

Aby wydrukować wszystkie wiersze w pliku tekstowym z wiersza poleceń (z rozszerzeniem opóźnionym):

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

Działa z wiodącymi białymi spacjami, pustymi liniami i białymi liniami.

Testowany na Win 10 CMD

Zimba
źródło
Boże, spróbuj, ale twoja pierwsza próbka usuwa ]]]linie wiodące z linii, druga próbka upuszcza puste linie i linie zaczynające się od spacji
jeb
Drugi służy do usuwania pustych linii. 1. można zmodyfikować, delimsjeśli dowolne wiersze w pliku tekstowym zaczynają się od ]np. zamień na jakiś znak, który tego nie robi, lub na znak kontrolny, taki jak Backspace lub Bell; zwykle nie występują w plikach tekstowych. Powodem delims=]jest usunięcie zastępcze stworzone przez /nz findpoleceniem, aby zachować puste linie.
Zimba
@jeb: brack]]] problem naprawiony. Zobacz aktualizację, aby wydrukować wszystkie linie w pliku tekstowym. Działa również na Win 10 CMD.
Zimba