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

#batch-file

#пакетный файл

Вопрос:

 for /f %%a in ('type "file.txt"^|find "" /v /c') do set /a count=%%a
 

Я нашел эту команду здесь http://www.dostips.com/?t=Snippets .Количество строк

Кажется, это работает, но я не могу понять, почему. Я неохотно использую что-то, чего я не понимаю, если только в нем нет ошибки для специальных символов и т. Д. Но я не могу понять, почему это работает.

Комментарии:

1. Введите find /? из командной строки и прочитайте, что /v /c делают переключатели and .

2. Насколько вы знакомы с batch? Ответ будет меньше, если мне не нужно объяснять, что for /f делает цикл.

3. Открутите команду. type "c:windowswin.ini" |find "" /v /c

4. Было бы полезно, если бы вы сказали нам, какую часть вы не понимаете. Если вы не понимаете for , у нас проблема.

5. Ну, с одной стороны, я тоже этого не понял, а потом заметил, что это batch , а не bash .

Ответ №1:

Наизнанку

  • type file.txt просто прочитайте файл и выведите его содержимое в стандартный вывод.
  • В этом коде выходные type данные команды передаются по конвейеру в find команду.
  • find Команда считывает стандартный ввод (не указан файл для чтения) и фильтрует его, ища строки, которые ничего не содержат ( /v ) (ничего find не соответствует, если указана пустая строка). Во время фильтрации он подсчитает, сколько найдено строк, и выведет в стандартный поток только количество совпадающих строк ( /c ). Поскольку пустая строка ничему не соответствует, но /v переключатель отрицает ее, мы заканчиваем сопоставление (и подсчет) всех строк в файле.
  • Две предыдущие переданные по каналу команды выполняются с помощью for /f команды. for /f используется для обработки строки, чтения содержимого файла или выполнения команды и обработки ее выходных данных.

примечание: по умолчанию команда, которая должна быть выполнена, заключена в одинарные кавычки в in предложении for /f команды

примечание: канал — это специальный символ, и чтобы включить его в for /f команду, нам нужно экранировать его ( ^| )

  • Для каждой строки (строки, каждой строки внутри файла или каждой строки в выходных данных команды) выполняется код внутри do предложения, при этом обрабатываемая строка (или некоторые ее части) сохраняется в for заменяемом параметре ( %%a в этом коде)
  • Выходные find данные команды (количество строк в файле) сохраняются в параметре for /f replacable , do предложение выполняется, и количество строк в файле (сохраненное в параметре replacable) копируется в переменную среды

примечание: set /a используется для арифметических операций. В данном случае в этом нет необходимости, и простая set команда должна выполнить всю работу, но, возможно, она была написана таким образом, чтобы было понятнее, что значение, которое будет сохранено в переменной среды, является числом

Комментарии:

1. «возможно, это было написано так, чтобы сделать его более понятным» — Да, или чтобы заставить его быть числом (0), если вывод по какой-то причине не числовой.

2. @GolezTrol, переменные среды всегда являются строками, /a просто вызывает отдельный анализатор для обработки арифметики, чего нет в этом коде. Я до сих пор не видел find /c , чтобы команда выводила какие-либо цифры, вы знаете, как это сделать?

3. Да, переменные среды всегда являются строками, но set /a var=XYZ приводит к превращению в var 0 . Таким образом, вы могли бы использовать /a здесь как приведение к типу, гарантируя, что var будет содержать «число» (строку, содержащую допустимое числовое значение) вместо текстового значения XYZ , которое может прервать следующий шаг. Это может быть использовано в качестве меры предосторожности или как способ облегчить проверку результата на следующем этапе. Обычно это должно работать, но я могу себе представить, что find может вернуть что-то еще в случае ошибки (файл нечитаемый, время ожидания сети и т. Д.).

4. Хорошо, быстрый тест показывает, что это действительно должно всегда работать и type "file.txt"^|find "" /v /c вернет ошибку, за которой следует 0, когда файл не найден, так что, возможно, эта мера предосторожности в конце концов не нужна. Но, возможно, автор этого кода этого не знал. 😉

5. @GolezTrol find выводит ошибки в stderr (не считывается for /f командой). Нет возможности ошибки файла find , поскольку он не считывает ни один файл, кроме передаваемых данных. Если полная внутренняя команда завершается с ошибкой и нет выходных do данных, предложение не выполняется, а переменная пуста (инициализации нет), или может быть извлечена строка, соответствующая другой переменной, и сгенерировать неправильное значение, или она может сгенерировать математическую ошибку, сбой и не инициализировать переменную, …есть способы, при которых это может привести к сбою, но set /a это не гарантирует отсутствия сбоя и здесь не требуется .