Cmd прочитать файл построчно

Обновлено: 03.07.2024

1 EXIT /b for %%a in ("A=a" "B=b" "C=c" "D=d" "E=e" "F=f" "G=g" "H=h" "I=i" "J=j" "K=k" "L=l" "M=m" "N=n" "O=o" "P=p" "Q=q" "R=r" "S=s" "T=t" "U=u" "V=v" "W=w" "X=x" "Y=y" "Z=z" "А=а" "Б=б" "В=в" "Г=г" "Д=д" "Е=е" "Ж=ж" "З=з" "И=и" "К=к" "Л=л" "М=м" "Н=н" "О=о" "П=п" "Р=р" "С=с" "Т=т" "У=у" "Ф=ф" "Х=х" "Ц=ц" "Ч=ч" "Ш=ш" "Щ=щ" "Ь=ь" "Ы=ы" "Ъ=ъ" "Э=э" "Ю=ю" "Я=я") do ( call set %

ЗАМЕНА ОДНОЙ ПОДСТРОКИ НА ДРУГУЮ В ФАЙЛЕ

В результате, в папке, где будет запущен приведенный выше текст, создастся файл sbs2.com.
Возможно, вы будете приятно удивлены его размером - 659 БАЙТ!
Те, кому вышеприведенные изыски кажутся излишними, могут скачать готовую утилиту здесь.
Использование:
sbs2.com 0 "Old String" "New String" < infile > outfile
Осуществляется замена всех вхождений Old String на New String в файле infile. Результат запишется в файл outfile.

Такую задачу можно решить без использования сторонних программ, только средствами bat !
Ниже приведен пример с использованием локальной процедуры txtrepl

setlocal ENABLEDELAYEDEXPANSION echo off call :txtrepl end finish C:\1\24i.bat C:\1\24i.ba1 pause exit :txtrepl rem param - find, repl, from, to set FINDTXT=%1 set REPLTXT=%2 if EXIST %3 ( set FILEFROM=%3 ) else ( echo error. Not found file %3 pause exit ) set FILEOUT=%4 set COUNT=0 for /F "tokens=*" %%n in (!FILEFROM!) do ( set /A COUNT=!COUNT!+1 set LINE=%%n set TMPR=!LINE:%FINDTXT%=%REPLTXT%! if !COUNT! == 1 ( Echo !TMPR!>!FILEOUT! ) else ( Echo !TMPR!>>!FILEOUT! ) ) exit /b rem end of proc

Вывод на экран, в файл текста без перевода строки

В bat/cmd командах не предусмотрена возможность вывода данных без перевода строки. Но для решения такой задачи можно использовать некую уловку.
Команда set с параметром, предусматривающим ввод данных с экрана, позволяет вывести подсказку для ввода без перевода строки. Вот этим мы и воспользуемся.
<nul set /p a=text В данном случае, слово text (а здесь может быть и переменная) будет выведено но экран без перевода строки. Значение переменной a при этом не будет изменено (если это для вас важно).
Соответственно, для вывода текста в файл без перевода строки используется конструкция:
<nul set /p a=text>b.txt

Использование этого приема в сочетании с символом backspace (код 08) позволяет сделать вывод на экран изменяемого текста и как вариант - "вращающейся палки".

Вычисление длины строковой переменной

В bat/cmd командах нет функции, позволяющей вычислять длину строковой переменной. А такая задача возникает не так уж и редко. Однако средств командного языка достаточно, для того что бы решить такую задачу, не прибегая к использованию специальных программ. Рассмотрим несколько вариантов решения данной задачи:

1 :startvarcount if not defined var exit /b set var=%var:

1% set /a %2+=1 goto startvarcount exit /b

set st=abcdefghijklmnopqrstuvwxyz . call :var_сount2 %st% count2 echo %count2%

Еще один вариант вычисления длины строковой переменной:

:StringLen :: ----------------------- :: Нахождение длины строки :: ----------------------- :: %1 - текстовая строка :: ----------------------- Set $StringLen=0 Set $StringBuf=%

1" GoTo :EOF :StringLenLoop Set /A $StringLen+=1 Call Set $StringChr=%%$StringBuf:

%$StringLen%%% If ""=="%$StringChr%" GOTO :EOF GoTo :StringLenLoop

Еще один способ определения длины строки, как ни странно - достаточно быстрый:

n0.tmp" For %%i In ("%TEMP%\%

n0.tmp") Do Set /A z=%%

Ну и, наконец, решение, поразившее меня своей математической лаконичностью:

:strLen string len -- returns the length of a string :: -- string [in] - variable name containing :: the string being measured for length :: -- len [out] - variable to be used :: to return the string length :: Many thanks to 'sowgtsoi', but also 'jeb' :: and 'amel27' dostips forum :: users helped making this short and efficient :$created 20081122 :$changed 20101116 :$categories StringOperation :$source http://www.dostips.com ( SETLOCAL ENABLEDELAYEDEXPANSION set "str=A!%

1!"&rem keep the A up front to ensure we rem get the length and not the upper bound rem it also avoids trouble in case of empty string set "len=0" for /L %%A in (12,-1,0) do ( set /a "len|=1%<<%%A" for %%B in (!len!) do ^ if "!str:

1<<%%A" ) ) ( ENDLOCAL & REM RETURN VALUES IF "%

set "string=12345678901234 " call :strLen string len echo len=%len%

Для себя я так же использую метод половинного деления для нахождения количества символов в строке. Эта процедура менее изящна, и, возможно, потребует несколько большего времени для вычислений, чем приведенная выше, но, на мой взгляд, она понятнее. (В этом месте надо было похвалить себя еще, но что-то не нашлось достойных эпитетов)
Привожу на всякий случай и эту процедуру ))

@echo off setlocal ENABLEEXTENSIONS SetLocal EnableDelayedExpansion set "string=123456789012345678901" call :strLen string len echo len=%len% pause exit :strLen string len :: - string [in] - variable name containing the string :: -- len [out] - variable to be used to return the string length SETLOCAL ENABLEDELAYEDEXPANSION set /a nn=10 & rem max length string = 2^^nn. rem If nn=10 - max length=1024 set /a mmin=0 set /a mmax=1"<<"%nn% set "str=Q!%1!" for /L %%A in (%nn%,-1,1) do ( set /a BB = ^(!mmin! + !mmax!^) ">>" 1 call set sim=%%str:

!BB!,1%% if "!sim!" == "" ( set /a mmax=!BB!) else ( set /a mmin=!BB! ) ) ENDLOCAL & SET /a %

2=%mmin% EXIT /b %mmin%

Получение подстроки.

Если смещение начала подстроки и ее длина являются константами - здесь все достаточно просто и аналогичный пример рассматривался выше:

Прошу прощения, если в качестве значения переменной str я опубликовал чей-то пароль )).
Если же одна или обе эти величины - переменные, то решение будет не столь простое.
Здесь встретиться возможно не совсем обычное применение команды CALL. Немного глубже об этом на странице Полезное в разделе Особенности использования команды CALL. Там же рассмотрен и этот пример.
Итак, рассмотрим возможные решения:

SetLocal EnableDelayedExpansion set str=123qwerty456 set n1=3 set n2=6 Set d2=!str:

Или как вариант предыдущего

setlocal ENABLEEXTENSIONS SetLocal EnableDelayedExpansion set str=zaq12wsx set n1=3 set n2=6 call :SUBSTRING str,%n1%,%n2% echo %SUBD% . :SUBSTRING set SUBD=!%1:

Удаление ведущих и замыкающих пробелов.

:ALLTRIM :: ----------------------- :: Krasner B. :: ----------------------- :: %1 - var with txt string :: ----------------------- SetLocal EnableDelayedExpansion set /a firstnoblank=-1 set /a lastnoblank=0 set /a curpos=1 set "str=Q!%1!" :StringLenLoop set SUBD=!str:

%curpos%,1! if "!SUBD!" == "" GoTo :formrez if NOT "!SUBD!" == " " ( if !firstnoblank! == -1 set firstnoblank=!curpos! set lastnoblank=!curpos! ) set /a curpos = !curpos!+1 GoTo :StringLenLoop :formrez set /a n1=!firstnoblank!-1 set /a n2=!lastnoblank!-!firstnoblank!+1 if !firstnoblank! == -1 (set "rez primer"> set "strr=" Call :ALLTRIM strr echo result ALLTRIM ^>%strr%^< . set "strrr= 22 33 " Call :ALLTRIM strrr echo result ALLTRIM ^>%strrr%^<

Для вопросов, обсуждений, замечаний, предложений и т. п. можете использовать раздел форума этого сайта (требуется регистрация).

Новый раздел о средствах командной строки в рамках этого же проекта расположен здесь

Команда FOR используется для выполнения команды, заданной в виде параметра, для каждого элемента из набора. В качестве элементов могут использоваться файлы, каталоги, наборы строк.

Формат командной строки:

FOR %переменная IN (набор) DO команда [параметры]

%переменная - Однобуквенный подставляемый параметр.

(набор) - Определяет набор, состоящий из одного или нескольких элементов, обрабатываемых командой.

команда - Команда, которую следует выполнить для каждого элемента набора.

параметры - Параметры для команды, выполняемой по отношению к элементам набора.

. В пакетных файлах для команды FOR используется запись

%%переменная вместо %переменная . Имена переменных учитывают регистр букв (%i отличается от %I).

Поддерживаются также дополнительные форма команды FOR:

FOR /D %переменная IN (набор) DO команда [параметры]

Ключ /D задает в качестве набора имена каталогов (не файлов).

FOR /R [[диск:]путь] %переменная IN (набор) DO команда [параметры]

Ключ /R задает выполнение команды для каталога [диск:]путь, а также для всех подкаталогов этого пути. Если после ключа /R не указано имя каталога, используется текущий каталог. Если набор - это одиночный символ точки (.), команда просто перечисляет дерево каталогов.

FOR /L %переменная IN (начало,шаг,конец) DO команда [параметры]

Ключ /L задает обработку набора из последовательности чисел с заданными началом, концом и шагом приращения. Так, набор (1,1,5) раскрывается в (1 2 3 4 5), а набор (5,-1,1) - в (5 4 3 2 1)

FOR /F ["ключи"] %переменная IN (набор-файлов) DO команда [параметры]

FOR /F ["ключи"] %переменная IN ("строка") DO команда [параметры]

FOR /F ["ключи"] %переменная IN ('команда') DO команда [параметры]

Ключ /F задает обработку файлов, строковых значений или результатов стандартного вывода другой команды. Набор файлов - содержит имена одного или нескольких файлов, которые по очереди открываются, читаются и обрабатываются. Обработка состоит в чтении файла, разбивке его на отдельные строки текста и разборе каждой строки в ноль или более подстрок. Затем вызывается тело цикла "for", при выполнении которого каждая найденная подстрока используется в качестве значения переменной. По умолчанию ключ /F выделяет из каждой строки каждого файла первую отделенную пробелами подстроку. Пустые строки в файле пропускаются. Необязательный параметр "ключи" служит для переопределения правил разбора по умолчанию. Он представляет собой заключенную в кавычки строку, содержащую одно или несколько ключевых слов для определения параметров разбора. Ключевые слова:

eol=символ - знак начала комментария в конце строки ( признак конца обрабатываемых данных строки). Задается в виде одиночного символа.

skip=n - число пропускаемых при обработке строк от начала файла.

delims=xxx - набор разделителей между обрабатываемыми элементами строк. По умолчанию, в качестве разделителей используются пробелы и знаки табуляции.

tokens=x,y,m-n - номера подстрок из каждой строки, передаваемые в тело цикла "for" для каждой итерации. Например, для обычного текстового файла, подстроками будут слова, а разделителями подстрок - пробелы или знаки табуляции. При использовании этого ключа выделяются дополнительные имена переменных. Формат m-n представляет собой диапазон подстрок с номерами от m по n. Если последний знак в строке tokens= является звездочкой, то создается дополнительная переменная, значением которой будет весь оставшийся текст в строке после разбора последней подстроки.

usebackq - режим обработки кавычек. Строка, заключенная в обратные кавычки, выполняется как команда, строка, заключенная в прямые одиночные кавычки, является строкой символов, а двойные кавычки могут использоваться для задания имен файлов, содержащих пробелы.

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

Выполняется разбор файла myfile.txt. Все строки, которые начинаются с символа точки с запятой (eol=; ), пропускаются. Вторая и третья подстроки из каждой строки ( tokens=2,3 ) передаются в тело цикла "for", причем подстроки разделяются запятыми и/или пробелами. В теле цикла переменная %i принимает значение второй подстроки, %j - третьей, а %k - все оставшееся поле до конца строки после третьей подстроки . Имена файлов, содержащие пробелы, необходимо заключать в двойные кавычки. Чтобы использовать двойные кавычки, необходимо использовать параметр usebackq, иначе двойные кавычки будут восприняты как определение строки-литерала для разбора.

В данном примере переменная %i явно объявлена в инструкции "for", а переменные %j и %k объявляются неявно с помощью ключа tokens= . Ключ tokens= позволяет извлечь из одной строки файла до 26 подстрок. Следует помнить, что имена переменных FOR являются однобуквенными , с учетом регистра, поэтому одновременно не может быть активно более 52 переменных, задаваемых как явно, так и неявно.

Команда FOR /F может также использоваться для обработки явно заданной строки, заключенной в одиночные кавычки и указанной в качестве параметра в скобках. Она будет разобрана так же, как одиночная строка, считанная из входного файла.

В качестве обрабатываемого набора, также, может быть использован вывод ( выходные данные ) другой команды. В этом случае используется в качестве параметра в скобках строка в обратных одиночных кавычках . Эта строка передается для выполнения дочернему обработчику команд CMD.EXE, а вывод этой команды сохраняется в памяти и разбирается так, как если бы это был файл. Пример:

FOR /F "usebackq delims= )
%

fI - переменная %I расширяется до полного имени файла
%

dI - из переменной %I выделяется только имя диска
%

pI - из переменной %I выделяется только путь к файлу
%

nI - из переменной %I выделяется только имя файла
%

xI - из переменной %I выделяется расширение имени файла
%

sI - полученный путь содержит только короткие имена
%

aI - переменная %I расширяется до атрибутов файла
%

tI - переменная %I расширяется до даты /времени файла
%

zI - переменная %I расширяется до размера файла
%

$path:I - проводится поиск по каталогам, заданным в переменной среды path , и переменная %I заменяется на полное имя первого найденного файла. Если переменная path не определена или в результате поиска не найден ни один файл, то этот модификатор заменяется на пустую строку.

При объединении нескольких операторов можно получить следующие результаты:

dpI - переменная I раскрывается в имя диска и путь

nxI - переменная I раскрывается в имя файла и его расширение

fsI - переменная I раскрывается в полный путь с короткими именами

dp$path:I - проводится поиск по каталогам, заданным в переменной среды path , и переменная I раскрывается в имя диска и путь к первому найденному файлу.

ftzaI - переменная I раскрывается в строку, подобную выдаваемой командой DIR

В приведенных выше примерах переменные I и path можно заменить на другие допустимые значения. Синтаксическая конструкция с символами

заканчивается допустимым именем переменной цикла FOR.

Для имен переменных рекомендуется использовать заглавные буквы, например - I , что делает эту конструкцию более удобной для чтения и предотвращает ошибочное принятие их за модификаторы, которые не различают регистр.

При использовании команды FOR в командных файлах, если внутри цикла нужно выполнить более одной команды, то они заключаются в скобки:

FOR %переменная IN (набор) DO (
команда1 [параметры]
команда2
. . .
)

@echo OFF
for /L %%I in (1,1,5) DO (
echo FIRST%%I
ECHO LAST%%I
)

Обычно, в командных файлах команда FOR используется не только для разбора данных, но и их обработки, что требует использования переменных внутри цикла FOR . И здесь возникает проблема - изменения значений переменных не происходит, т.е. их применение внутри скобок невозможно. Подобное явление вызвано не логическими предпосылками, а всего лишь определенными особенностями реализации командного процессора CMD.EXE , и это нужно обязательно учитывать при обработке переменных внутри циклов команд FOR и IF. Другими словами, использование значений переменных внутри скобок, требует изменения стандартного режима интерпретации командного процессора. Разработчиками предусмотрена возможность запуска CMD.EXE с параметром /V:ON , что включает разрешение отложенного расширения переменных среды с применением символа восклицательного знака ( ! ) в качестве разделителя. То есть, параметр /V:ON разрешает использовать !var! в качестве значения переменной var во время выполнения внутри циклов команд FOR и IF . Но на практике чаще используется возможность локального включения данного режима внутри командного файла специальной директивой:

После чего, можно обрабатывать принимаемые переменными значения внутри цикла, используя вместо знаков процента восклицательные знаки. Синтаксически, использование обоих разделителей допускается, но результаты этого использования будут разными, что наглядно демонстрируется следующим командным файлом:

Setlocal EnableDelayedExpansion
@ECHO OFF
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "!VAR!" == "after" @echo Со знаком процента=%VAR% , Со знаком вопроса=!VAR!
)

Команда set VAR=after выполняется внутри подпрограммы, ограниченной скобками и, если убрать команду Setlocal EnableDelayedExpansion или не использовать для получения значения переменной VAR восклицательные знаки, ее значение останется старым ( тем, что было установлено до входа в цикл команды FOR ).

Данная особенность реализации командного процессора Windows нередко приводит к неожиданным результатам при использовании групп команд, объединенных скобками в конструкциях FOR и IF и тогда, когда значение какой-либо переменной изменяется внутри цикла с одной командой. Например, для получения списка файлов текущего каталога такой командный файл работать не будет:

set LIST=
for %%i in (*) do set LIST=%LIST% %%i
echo %LIST%

Вроде бы, логически все верно, но не учтена особенность обработки значений переменных. Значение переменной LIST внутри цикла команды FOR изменено не будет, оно останется пустым ( задано командой SET LIST= ), каким и было на начало цикла FOR. Команда SET LIST= %LIST% %%I должна в каждом цикле менять значение переменной LIST на текущее, плюс символ пробела, и плюс текущее значение переменной I , которое принимает значение имени файла в текущем каталоге. Синтаксически, команда верная, но из-за озвученной выше особенности реализации командного процессора - не работает, и значение переменной LIST не изменяется. Для того, чтобы это произошло, командный файл нужно изменить, таким же образом, как и в примере для группы команд:

Setlocal EnableDelayedExpansion
set LIST=
for %%i in (*) do set LIST=!LIST! %%i
echo %LIST%

Теперь, значение переменной LIST внутри цикла FOR будет изменяться, последовательно принимая значения имен файлов, разделенных пробелом ( set LIST=!LIST! %%i ).

Эту особенность реализации CMD нужно учитывать и при использовании значений системных переменных внутри циклов, как например, переменной ERRORLEVEL:

Командой FOR задаётся список команд, которые выполняются с КАЖДЫМ элементом набора.
Набор * пишется внутри IN (. )
Список команд пишется внутри DO (. )
Командная строка выполняет эти команды раз за разом, при этом текущий элемент набора находится в переменной, заданной после %% (назовём ее переменной цикла).

выведет имена и путь ко всем файлам с расширением .txt в папке C:\Users.

* Примеры под спойлером

Для команды For без ключей набором может являться :

1) Маска файлов* (или путь + маска файлов)
- в двойных кавычках, или без них:

IN (*.txt)
Результат: список файлов с расширением .txt в текущем каталоге.

IN (*.txt *.bat)
Результат: список файлов с расширениеми .txt и .bat в текущем каталоге.

IN ("C:\Folder 1\Doc_31-12-*.txt")
Результат: тот же. Но поиск ведется в каталоге C:\Folder 1 (заметьте с пробелом в имени);
имя файла начинается на Doc_31-12-

Прим.: FOR без ключа не умеет выводить список каталогов.
* маска файлов - это набор файлов, заданный с помощью подстановочных знаков * и/или ?
где * - обозначает 0 или больше любых символов в имени файла.
а ? - означает 0 или 1 любой символ в имени файла.

2) Строка
- в двойных кавычках, или без них:

Строкой считается любая последовательность символов, если она не содержит знаков маски * или ?
Смысл цикла здесь в том, чтобы разбить такую строку по пробелам (или знакам табуляции)
и выполнить с каждой подстрокой список команд.

Если мы хотим, чтобы какая-то из строк не "билась" по пробелам, укажем ее в двойных кавычках:
При этом, чтобы не выводились сами кавычки "" мы используем модификатор*

(тильда) при раскрытии переменной цикла %%

*О других модификаторах переменной цикла можно почитать здесь и здесь.

3) еще есть смешанный тип. Это когда в наборе стоит маска (1-й описанный тип), а через пробел Строка (2 тип). ведет себя вполне ожидаемо, но вряд ли найдет себе применение.

О наборах для FOR с ключем /F далее в нижнем спойлере.


Ключ /F часто используется для построчного разбора файла, т.е.

выведет все строки файла 1.txt, который находится в корне диска C.

UseBackQ (Use back quotes) означает, что набор с двойными кавычками * подразумевает передачу в цикл имени файла.
delims= означает, что в переменную %%a будет записана вся строка (без разделения по пробелу или знаку табуляции, т.к. стандартный разделитель заменен на NULL (пустой символ).
В такой вариации:
tokens=* приводит к тому же результату, что и delims= . Означает прекратить разбивку по разделителю после "0-го" токена, т.е. сразу же.

* Этот вариант необходим для работы с файлом, путь или имя которого содержит пробелы.
Можно было не использовать UseBackQ , тогда команда приняла бы вид:

но такая конструкция восприняла бы пробел в имени как определение нового файла, поэтому UseBackQ более приемлем.

** Примеры под спойлером

В цикле FOR /F вид задаваемого набора зависит от формы кавычек в IN (. ) , а также наличия ключевого слова UseBackQ

Виды наборов для FOR /F:
1) Набор файлов (задание маски недопустимо!)

без UseBackQ - задается без кавычек IN (. )
__ с UseBackQ - может задаваться как в кавычках так и без них. IN (. ) IN (". ")

Функционал: чтение содержимого файла(ов) построчно в переменную цикла!

Принцип работы: источником для разбиения по разделителю (delims) является содержимое файла, заданного внутри IN (. ) или файлов, если они заданы через пробел.

Исключение: принятый по-умолчанию разделитель (пробел и знак табуляции) для этой конструкции цикла не применяется.

А что получится, если установить delims= (возле равно - знак пробела) ?

В выводе на экран командой Echo %%a мы получим содержимое файла, где каждая из строк будет напечатана до первого встретившегося пробела.

2) Строка (допускаются практически любые символы)

без UseBackQ - задается с двойными кавычками IN (". ")
__ с UseBackQ - задается с одиночными прямыми кавычками IN ('. ')

3) Команда (сначала выполняется она, а уже ее результаты обрабатываются циклом как строка(-и))

без UseBackQ - задается с одиночными прямыми кавычками IN ('. ')
__ с UseBackQ - задается с одиночными обратными кавычками IN (`. `)

1.1. Чтение файла - Набор файлов

Результат: выведет подряд содержимое двух файлов - 1.txt и 2.txt из каталога c:\users
Прим.: Echo. - с точкой - это обход ошибки, чтобы можно было напечатать пустую строку, точнее строку с пробелами.

1.2. Чтение файла - Набор файлов + UseBackQ
Получаем возможность использовать пробелы.

Результат: выведет содержимое файла 1.txt из каталога c:\folder 1
(заметьте, в имени папки есть пробел).

Результат такой же.

3.1. Команда

Сначала выполняется Dir /AD-L , которая выводит информацию о папках в текущем каталоге.
Вот что попадает под разбор циклу:

Далее цикл разбирает каждую строку по пробелам и табуляции на подстроки (токены).
На примере 1-й строки:
1-й токен (%%a)=29.12.2012 . 2-й токен (%%b)=15:16 . 3-й токен (%%c)=<DIR> . 4-й токен (%%d)=Favorites
.
Результат через Echo выводится на экран:

Папка Favorites Дата модификации 29.12.2012. Время 15:16
Папка Links Дата модификации 14.01.2013. Время 01:51
. и т.д. Результат такой же.
Альтернативный вариант нужен с целью, если одна из выполняемых команд требует точно такие же кавычки как и ключевое слово IN (. ).
Дабы не пользоваться символом экранирования, просто применяем другие кавычки.

Отличительной особенностью FOR /F является умение работать через токены * ,
а также поддержка дополнительных ключевых слов:
1) eol - знак комментария в начале строки (1-й символ). Т.е. строки с таким символом не будут обрабатываться. (по умолчанию, знак точки с запятой ; )
2) skip - пропуск определенного кол-ва обрабатываемых строк от начала файла
3) delims - задать другой разделитель(-ли) (по умолчанию, пробел и знак табуляции)
4) tokens - количество получаемых токенов (подстрок) в теле цикла и пределы разбивки по разделителю.
Также можно задать конкретный № токена, который попадет в первую переменную цикла.
5) usebackq - изменение правил использования кавычек внутри IN (. )

Детальную справку можно получить, введя в консоль команду FOR /?

* Токены - это подстроки, которые попадают в переменные цикла %% в каждой из итераций.
Они получаются в результате разбивки строки, заданной в IN (. ), по разделителю, заданному в Delims= (по умолчанию, пробел и знак табуляции).

В отличие, от FOR без ключа, в FOR /F все токены (все подстроки одной строки) попадают сразу В ПЕРВУЮ ИТЕРАЦИЮ цикла.
Они будут распределены по РАЗНЫМ переменным цикла, идущим в алфавитном порядке*, начиная с буквы, заданной после FOR /F %%











Здесь хотелось бы заметить, что проблема с кодировками будет при написании скрипта, на любом из родных для системы языков - cmd, vbscript, jscript.

Можно только сожалеть об отсутствии и решить эту проблему одним из следующих способов:
1. установить один из пакетов, содержащих достаточный набор команд, чтобы быть также уверенным как в командной строке unix, например, UnixUtils, Cygwin, GnuWin32
Иногда это не возможен из-за политик компаний, запрещающих самостоятельно устанавливать дополнительное ПО.
2. использовать PowerShell
Хотя все идет к тому, что PowerShell будет предустановлен на всех Windows, однако еще много систем на которых его нет. А установить нельзя.
3. написать собственный скрипт
Это уже выход, если 1 и 2 противопоказаны. Хотя есть свои недостатки (например упомянутая проблема - кодировки).

Я решил попробовать (частично или полностью) эмулировать работу некоторых важных команд обработки текстовых файлов средствами самой командной строки. Just for fun!
.
1. Количество строк в файле
Оказывается почти точно определить количество строк в файле очень просто:

И вот пример. Данная команда выводит немного дополнительной информации

Сказав "почти точно", я имел в виду, то что иногда результаты отличаются от видимого. Но этим грешат многие команды. Например, wc -l отбрасывает последнюю строку, если она не заканчивается переводом строки. В случае с find /c /v "" наблюдается расхождение с действительностью, если в конце файла несколько (более 2) пустых строк. По-видимому разные программы работают по разному - одни считают количество строк, другие количество переводов строк. И вследствие этого они могут различаться. Поэтому я рекомендую использовать следующее решение.

Команда выведет только размер файла в строках. И это самый точный способ узнать количество строк в файле.

Коли я упомянул в самом начале PowerShell, приведу примеры реализации с его помощью (я не знаток его синтаксиса и тонкостей, поэтому привожу некоторые, известные мне реализации, возможно не самые удачные, но полностью рабочие). Прелесть этих решений еще в том, что это однострочные команды (вики на англ):

.
2. Прочитать n последних строк в файле. Эмуляция команды tail
Оказывается, это очень простая задача:
1. узнать N - количество строк в файле;
2. вывести n строк, пропустив N-n:

.
Код на PowerShell:

.
3. Вывод нескольких начальных строк файла. Эмуляция команды head
Этот эмулятор я написал первым, хотя он не самый простой в реализации. Возможно, существуют варианты лучше, но, к сожалению, я их не нашел и, поэтому, я использовал "хак" с временным файлом. Суть его в том, что вначале создается временный файл, который содержит n-ое количество следующих строк:

то есть все номера требуемых строк.

Затем читается искомый файл, при этом каждая строка нумеруется, а команда поиска ищет только те строки номера которых соответствуют номерам из заданного временного файла.

.
И на последок, традиционно, код на PowerShell:

.
Послесловие
Здесь я привел только заготовки, но уже рабочие заготовки, которые частично решают проблему отсутствия полезных команд. Для полноценной эмуляции можно предусмотреть работу не только с заданным файлом или группой файлов, но и с консолью, и реализовать конвейерную обработку. Также можно было бы добавить проверку установки PowerShell в системе и, если он есть, выполнять его команды.

хеад и тайл в одном флаконе

smaharbA, как во флаконе дело обстоит с пустыми строками в файле?

  • Rumata
  • Разработчик
  • Неактивен











smaharbA
alexii
Коллеги. Во флаконе только head. Там нет tail.

есть там тайл - смотрите внимательно

alexii - не знаю, должно быть вроде как нормально, поправьте

smaharbA, я имел в виду, что разбор «for /f» пропускает пустые строки.

  • Rumata
  • Разработчик
  • Неактивен











Согласен. Но это не совсем то. В отличие от tail, more +N пропускает N строк из потока. И результат совершенно не предсказуем для потока в конвейере.

  • Rumata
  • Разработчик
  • Неактивен











разбор «for /f» пропускает пустые строки

Но вот посмотрите на этот пример:

  • greg zakharov
  • Разработчик
  • Неактивен

Код на PowerShell:
echo (get-content -path %windir%.

Слишком сложно, не находите?

А если нужно передать команду PoSh, то будет примерно так:

  • blackfox.blacktail
  • Участник
  • Неактивен
  • Рейтинг : [ 0 | 0 ]

Добрый день.
Использовал пример для подсчета количества строк в файле:

13 Ответ от smaharbA 2013-09-01 10:37:46

чем не устраивает ?

14 Ответ от blackfox.blacktail 2013-09-03 10:22:45

  • blackfox.blacktail
  • Участник
  • Неактивен
  • Рейтинг : [ 0 | 0 ]

2smaharbA
Если есть пустая строка, с символом SUB, её тоже считает.
Проще избавиться от этого символа, что я и сделал.
(При использовании copy, нужно поставить ключ /B)

15 Ответ от greg zakharov 2013-09-03 15:52:47

  • greg zakharov
  • Разработчик
  • Неактивен

EQU

Если есть пустая строка, с символом SUB, её тоже считает.

На оном спотыкается и Ruby (версия старая, до установки последней дело никак не доходит).

16 Ответ от smaharbA 2013-09-03 17:27:15

17 Ответ от greg zakharov 2013-10-13 10:27:59 (изменено: greg zakharov, 2013-10-13 10:28:42)

  • greg zakharov
  • Разработчик
  • Неактивен

Возможно, существуют варианты лучше, но, к сожалению, я их не нашел и, поэтому, я использовал "хак" с временным файлом.

head без временных файлов.

Может быть, но сколько бы не пробовал на выходе одинаковый результат. Может у меня на Win2k3 find специфический?

18 Ответ от Мальчик-гей 2013-10-17 09:04:37

  • Мальчик-гей
  • Участник
  • Неактивен

Может быть, но сколько бы не пробовал на выходе одинаковый результат.

Коллега smaharbA прав:

19 Ответ от greg zakharov 2013-10-17 11:51:48

  • greg zakharov
  • Разработчик
  • Неактивен

Смысл то один и тот же - количество строк в файле. А отбрасывать из вывода имя файла - дело вкуса. Так что это скорее "не равноценно", нежели "не эквивалентно". Или Вы русский язык как-то на свой лад интерпретируете?

20 Ответ от Rumata 2013-10-17 13:17:45

  • Rumata
  • Разработчик
  • Неактивен











greg zakharov
В данном случае smaharbA прав. Результат обеих команд одинаковый, но вывод - разный. Это как в JavaScript

21 Ответ от Мальчик-гей 2013-10-21 13:38:14

  • Мальчик-гей
  • Участник
  • Неактивен

Так что это скорее "не равноценно", нежели "не эквивалентно". Или Вы русский язык как-то на свой лад интерпретируете?

Дорогой коллега! Я понимаю эквивалентность вполне академически, как отношение, обладающее свойствами рефлексивности, симметричности и транзитивности. И в этом смысле на одном и том же классе объектов могут быть заданы различные отношения эквивалентности, так что объекты эквивалентные в одном отношении не будут эквивалентны в другом. Вспомните хотя бы конгруэнтность и подобие геометрических фигур. В рамках же этой темы требовалась более сильная эквивалентность, с совпадением формата вывода результатов, так как всё началось с

Команда выведет только размер файла в строках.

чему smaharbA и предложил эквивалентную именно в этом отношении замену.
По поводу "равноценно" и "эквивалентно" советую заглянуть в словарь, а ещё лучше, попробовать самому догадаться как же слово "эквивалентно" переводится на русский.

22 Ответ от greg zakharov 2013-10-21 15:07:13 (изменено: greg zakharov, 2013-10-21 16:40:40)

  • greg zakharov
  • Разработчик
  • Неактивен

. советую заглянуть в словарь, а ещё лучше, попробовать самому догадаться как же слово "эквивалентно" переводится на русский.

Простите, у Вас филологическое образование? Или Вы страдаете дислексией, что не вполне можете разуметь написанное? Тем паче, что

Я понимаю эквивалентность вполне академически, как отношение, обладающее свойствами рефлексивности, симметричности и транзитивности.

Вы сами дали понять, что всякую иную интерпретацию слова "эквивалентность" Вы просто-напросто игнорируете, что сужает Ваш кругозор до ортодаксального математического видения проблемы, вкупе с дезинтеграцией русского языка как такового, из чего следует заключить, что спор с Вами представляется трюизмом, а точнее софистикой, - ни одного аргумента с Вашей стороны не последовало.

undefined == null // true
undefined === null // false

Не приплетайте сюда, пожалуйста, javascript. null и undefined - это два тривиальных типа данных, каждый из которых определяет только одно значение. Однако, заявлять об их эквивалентности, как-то однако. Считается, что у значение null - объектный тип. При всем этом значение null уникально и отличается от любых других. Если переменная равна null, значит в ней не содержится допустимого объекта (массива, числа, строки и т.д.) undefined же возвращается же либо при обращении к переменной, которй никогда не присваивалось значение, либо к свойству объекта которого не существует. При этом null и undefined не эквивалентны друг другу, несмотря на то, что оператор эквивалентности считает их равными, - это написано в любой книге по javascript. Это можно также утверждать и потому, что в отличии от null значение undefined не является зарезервированным словом. Если будет время, почитайте на досуге, например, Дэвида Флэнегана, если точно помню и не делайте скоропалительных выводов.
Резюмирую, несмотря на общую схожесть многих языков, абсолютизировать понятие эквивалентности не стоит, - если не каждый, то некоторые из языков вкладывают собственное понятие в "эквивалентность", причем будь то естественный язык или язык программирования. То, что выдает в командном языке одинаковый результат, но лишь с некоторым "мусором", знаете ли еще не повод утверждать что заяц - это волк и вообще не млекопитающее, а аргументы г-на Мальчик-гей не убедительны, ибо таким образом можно доказать все что угодно, в том числе что и Ленин был грибом.

Читайте также: