У меня есть командный файл, который вызывает инструмент. Теперь я столкнулся с проблемой в пакетном файле в цикле 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
часть кода, стандартная ошибка перенаправляется на стандартный вывод, но что произойдет, если я удалю ее полностью? Перенаправляет ли он на какой-то другой вывод, а также почему он перестает повторять команду?
Эта одна строка имеет много функциональных возможностей. Резюме на простом английском языке будет примерно таким:
Давайте разберемся.
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
.