我有一个调用工具的批处理文件。现在我在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
回复 Doug Deden 的示例:
当我在下面执行时,它确实显示了 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
- 将任何错误重定向到与标准输出相同的位置(Rob van der Woude 有一个很棒的关于重定向的页面) - 你需要这个,因为 Java 将其版本信息发送到标准错误流而不是标准输出流 - 看到这个StackOverflow 上的问答——这使它将版本信息发送到标准输出流,因此最终可以被findstr
|
- 将目前的结果发送到下一个程序 -findstr
findstr
- 在输入中搜索一个字符串,也就是java -version 2>&1
命令的输出/i
- 告诉findstr
进行不区分大小写的搜索"version"
- 告诉findstr
要搜索什么文本的典型输出
java -version
如下所示:然后在通过之后
findstr
,你只剩下包含“版本”的行:接下来,我们来看看这
for /f
件作品。for /f … in …
将查看“in”后面的命令的结果并对其进行处理。您的第一个和第三个示例对该部分具有不同的值tokens=…
,因此在复制和粘贴时可能会丢失某些内容。在任何情况下,该tokens=…
部分都会告诉for /f
命令正在处理的行的哪些部分(又名标记)需要关注。默认情况下,空格或制表符表示新标记。因此,参数 oftokens=3
会告诉for /f
您查看该行的第三部分,即"1.8.0_92"
. 该%%g
选项告诉for /f
将它找到的内容存储在变量中%g
。(需要额外%
的,因为您是从批处理文件运行它。如果您直接在命令提示符下运行它,则只需要一个%
.)到目前为止,如果您使用
tokens=3
,您将"1.8.0_92"
存储在%g
变量中。(如果您tokens=1-3
改为使用,您将拥有"java"
in%g
、version
in%h
和"1.8.0_92"
in%i
。该for /f
命令开始将标记推入以您指定的变量开头的变量中,并在字母表中递增。)然后,该
do
行的一部分告诉您要为for /f
命令提出的每件事执行什么命令。在这种情况下,它做了两件事:@echo Debug Output: %%g
- 将“调试输出:”打印到标准输出,然后是%g
变量的值,我们之前看到的是"1.8.0_92"
.set JAVAVER=%%g
- 将JAVAVER
环境变量的值设置为变量中的任何%g
值。(Rob van der Woude 也有一个很棒的页面来解释for/f 命令。)
当您在其中一个实验中取出
findstr
零件并使用tokens=3
时,您会看到输出表明该for /f
命令抓取了 Java 版本信息的每一行上的第三个标记,此处以粗体突出显示:并且该实验还会将 JAVAVER 环境变量设置为这些字符串中的每一个,因此它会以最后一个 -- 结束
64-bit
。