Як ви переглядаєте кожен рядок у текстовому файлі, використовуючи пакетний файл Windows?


244

Я хотів би знати, як провести цикл через кожен рядок у текстовому файлі, використовуючи пакетний файл Windows та обробляти кожен рядок тексту підряд.

Відповіді:


304

Подані нижче публікації дуже допомогли, але не зробили те, про що я говорив у своєму запитанні, де мені потрібно обробити весь рядок у цілому. Ось що я знайшов працювати.

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

Ключове слово лексеми зірочкою (*) потягне весь текст для всього рядка. Якщо ви не введете зірочку, вона лише виведе перше слово на рядку. Я припускаю, що це стосується пробілів.

Для команд на 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
FYI, якщо вам потрібно виконати багаторядкову команду, після "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"!
Ден Стівенс

1
Варто зазначити, що параметр індексу у вашому циклі повинен бути одним символом. Так, наприклад,%% i нормально, але індекс %% не зможе.
Вінсент

59

З посилання на командний рядок Windows:

Щоб розібрати файл, ігноруючи коментовані рядки, введіть:

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

Ця команда аналізує кожен рядок у Myfile.txt, ігноруючи рядки, які починаються з крапки з комою та передаючи другий та третій жетони від кожного рядка до тіла FOR (лексеми розмежовані комами чи пробілами). Тіло оператора 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

У пакетному файлі ви ОБОВ'ЯЗКОВО використовувати %%замість %: (Тип 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

Що це робить: "виконувати виклик: процес %% i %% j %% k" наприкінці команди for передає інформацію, отриману в команді for, з myfile.txt в "підпрограму" "процес".

Коли ви використовуєте команду 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 з командного рядка; із пакетного сценарію потрібно додати додатковий%, як показано нижче:

---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 у наведеному вище прикладі) є пробіл (наприклад, "мій файл.txt" або "c: \ програмні файли"), використовуйте:

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

, із ключовим словом типу, що викликає typeпрограму, яка відображає вміст текстового файлу. Якщо ви не хочете зазнавати накладних витрат на виклик команди type, слід змінити каталог у каталог текстового файлу. Зауважте, що тип усе ще потрібен для імен файлів з пробілами.

Я сподіваюся, що це комусь допоможе!


Не потрібно префіксувати ім’я файлу, оскільки пакетний файл буде виглядати у поточній папці за замовчуванням.
foxidrive

1
@foxidrive: Гаразд, я вас чую. Хоча слід бути обережним. Наприклад, якщо каталог було змінено, він виглядатиме не в тому каталозі, а в тому, в якому знаходиться пакетний файл. Тоді рішення повинно викликати **cd /d %~dp0**цикл for. Це переконається, що ви посилаєтесь на файл у каталозі, в якому знаходиться пакетний файл. Дякую за спостереження
Marvin Thobejane

2
Thx та +1 для typeобходу
halex

Я не можу typeобійти роботу, мені довелося процитувати своє ім'я файлу, оскільки воно знаходиться в іншому каталозі, який містить пробіли (Чорт ти Program Files). Я отримую помилкуThe system cannot find the file `type.
scragar

1
@scragar, ти отримав правильну цитату? це має бути "не". На моїй клавіатурі він знаходиться на тій самій клавіші, що і @
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 використовується для префіксації кожного рядка з номером рядка та двокрапкою, тому порожні рядки більше не порожні.

Відкладене розширення потрібно вимкнути, коли отримувати доступ до %%aпараметра, інакше знаки оклику !та піклування ^будуть втрачені, оскільки в цьому режимі вони мають особливі значення.

Але для видалення номера рядка з нього потрібно включити затримку розширення.
set "var=!var:*:=!"видаляє всі до першої кишки (використання delims=:видалить також усі двокрапки на початку рядка, не тільки ту, що знаходиться з findstr).
Endlocal знову відключає затримку розширення для наступного рядка.

Єдине обмеження - це обмеження довжини лінії ~ 8191, але, здається, немає способу подолати це.


Win 10 не дозволяє setlocalв командному рядку. Коли я запускаю код на CMD, я отримую! Var! замість заготовок. Як виправити?
Зімба

Межу довжини рядка можна подолати, розділивши файл на тимчасові файли з максимальною довжиною рядка 8190 перед обробкою. Потім рекомбінується в один файл.
Зімба

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

Прийнятий відгук, що використовує 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 Мб, що містить понад 2 мільйони рядків, де for /F ...команда застрягла після кількох тисяч рядків.

Про відмінності між foreachта ForEach-Object, див. Ознайомлення з ForEach та ForEach-Object .

(кредити: читайте файл за рядком у 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

Щоб надрукувати всі рядки в текстовому файлі з командного рядка (із затримкою розширення):

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


Бог спробувати, але ваші перші зразки видаляє провідні ]]]з ліній, другий зразок краплі порожні рядки і рядки , що починаються з простором
Джеб

Другий призначений для видалення порожніх рядків. 1-й можна змінити, delimsякщо будь-які рядки в текстовому файлі починаються з ]напр. замінити на якийсь символ, який не має, або керуючий символ на зразок зворотної області чи дзвоника; вони зазвичай не знаходяться в текстових файлах. Причина delims=]полягає у видаленні наповнювачів , створені /nз findкоманди , щоб зберегти порожні рядки.
Зімба

@jeb: bracket]]] Виправлена ​​проблема. Дивіться оновлення для друку всіх рядків у текстовому файлі. Працює і на Win 10 CMD.
Зімба
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.