Назад | Перейти на главную страницу

Понимание команд в пакетном скрипте

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

for /f "tokens=1-3" %%g in ('java -version 2^>^&1 ^| findstr /i "version"') do (    @echo Debug Output: %%g    set JAVAVER=%%g  )

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

('java -version 2^>^&1 ^| findstr /i "version"')

Также, чтобы добавить к моему недоумению, если я запустил команду ниже отдельно, она выдаст результат, как показано ниже, в котором нет текста «версия». Но та же команда, если я запускаю вместе, как указано выше, дает вывод текущей версии java.

Код:

for /f "tokens=3" %%g in ('java -version 2^>^&1') do (    @echo Debug Output: %%g    set JAVAVER=%%g    )

Вывод:

Debug Output: "1.8.0_231"
Debug Output: Runtime
Debug Output: 64-Bit

Пример ответа Дагу Дедену:

Когда я делаю это ниже, он отображает вывод команды echo.

for /f "tokens=3" %%g in ('java -version 2^>^&1 ^| findstr /i "version"') do (
@echo Debug Output: %%g
set JAVAVER=%%g
@echo %JAVAVER%
)

Но когда я сделаю это, удалив 2^>^&1, он не учитывает эхо команды.

Мое замешательство, когда я ставлю 2^>^&1 часть кода, стандартная ошибка перенаправляется на стандартный вывод, но что произойдет, если я удалю ее полностью? Перенаправляет ли он на какой-то другой вывод, а также почему он перестает повторять команду?

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

  • Спросите у Java, какая это версия. Это дает несколько частей информации.
  • Найдите в выводе Java строку, содержащую «версию».
  • Найдите третий компонент в этой строке.
  • Повторите это как вывод, а также установите для переменной среды JAVAVER это значение.

Давайте разберемся.

for /f "tokens=1-3" %%g in ('java -version 2^>^&1 ^| findstr /i "version"') do ( @echo Debug Output: %%g set JAVAVER=%%g )

Начну с самого сокровенного: 'java -version 2^>^&1 ^| findstr /i "version"' Пакетный файл указывает Windows запустить это, а затем пакетный файл что-то сделает с результатом.

Каретки (^) служат для указания командному файлу буквально обрабатывать следующие символы. В противном случае командный файл будет пытаться интерпретировать их и рассматривать как инструкции или модификаторы для самого командного файла. Вместо этого мы хотим, чтобы командный файл просто передавал их «как есть». Итак, командный файл сообщает Windows, что нужно запустить это:

'java -version 2>&1 | findstr /i "version"'

  • java - бегать java.exe, где бы он ни находился на Пути
  • -version - сказать java.exe чтобы распечатать информацию о версии и выйти
  • 2>&1 - перенаправлять любые ошибки в то же место, что и стандартный вывод (у Роба ван дер Вуде отличный страница о перенаправлении) - вам это нужно, потому что Java отправляет информацию о своей версии в стандартный поток ошибок, а не в стандартный поток вывода - см. этот вопрос и ответ на StackOverflow - вместо этого он отправляет информацию о версии в стандартный поток вывода, так что в конечном итоге она может быть увидена findstr
  • | - отправить полученные результаты в следующую программу - findstr
  • findstr - поиск строки на входе, которая является выходом java -version 2>&1 команда
  • /i - сказать findstr выполнять поиск без учета регистра
  • "version" - сказать findstr какой текст искать

Типичный выход java -version будет выглядеть так:

java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

А потом, пройдя через findstr, у вас останется только строка, содержащая слово «версия»:

java version "1.8.0_92"

Далее давайте посмотрим на for /f кусок. for /f … in … будет смотреть на результат команды, следующей за "in", и обрабатывать его. Ваш первый и третий примеры имеют разные значения для tokens=… часть, так что что-то могло быть потеряно при копировании и вставке. В любом случае tokens=… часть говорит for /f команда, о которой нужно заботиться о частях (также называемых токенами) обрабатываемой строки. По умолчанию пробел или табуляция обозначают новый токен. Итак, параметр tokens=3 скажет for /f посмотреть на третий отрезок линии, который "1.8.0_92". В %%g опция говорит for /f хранить то, что находит, в переменной %g. (Дополнительный % требуется, потому что вы запускаете его из командного файла. Если вы запускаете его прямо из командной строки, вам понадобится только один %.)

Пока, если вы используете tokens=3у тебя будет "1.8.0_92" хранится в %g переменная. (Если вы использовали tokens=1-3 вместо этого у вас будет "java" в %g, version в %h, и "1.8.0_92" в %i. В for /f команда начинает вставлять токены в переменные, начиная с указанной вами переменной и увеличиваясь по алфавиту.)

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

  • @echo Debug Output: %%g - выведите «Debug Output:» для стандартного вывода, за которым следует значение %g переменная, которую мы видели ранее, "1.8.0_92".
  • set JAVAVER=%%g - установить значение JAVAVER переменная окружения к тому, что находится в %g переменная.

(У Роба ван дер Вуда также есть отличная страница, объясняющая команда for / f.)

Когда вы вынули findstr участвовал в одном из ваших экспериментов и использовал tokens=3, вы видели вывод, указывающий, что for /f команда захватила третий токен в каждой строке информации о версии Java, выделенной здесь жирным шрифтом:


java version «1.8.0_92»
Java(TM) SE Время выполнения Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-битный Server VM (build 25.92-b14, mixed mode)

И этот эксперимент также установил бы переменную среды JAVAVER для каждой из этих строк, так что в итоге получилась бы последняя - 64-bit.