AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 1005282
Accepted
MitSM
MitSM
Asked: 2020-03-03 04:26:55 +0800 CST2020-03-03 04:26:55 +0800 CST 2020-03-03 04:26:55 +0800 CST

Batch 脚本中的命令理解

  • 772

我有一个调用工具的批处理文件。现在我在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部分放入代码中时,标准错误被重定向到标准输出,但是如果我完全删除它会发生什么?它是否重定向到其他一些输出,以及为什么它停止回显命令?

windows batch-file
  • 1 1 个回答
  • 704 Views

1 个回答

  • Voted
  1. Best Answer
    Doug Deden
    2020-03-03T15:11:58+08:002020-03-03T15:11:58+08:00

    那一行有很多功能。一个简单的英文摘要会是这样的:

    • 问 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- 将任何错误重定向到与标准输出相同的位置(Rob van der Woude 有一个很棒的关于重定向的页面) - 你需要这个,因为 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命令正在处理的行的哪些部分(又名标记)需要关注。默认情况下,空格或制表符表示新标记。因此,参数 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、versionin%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 版本信息的每一行上的第三个标记,此处以粗体突出显示:

    
    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)
    

    并且该实验还会将 JAVAVER 环境变量设置为这些字符串中的每一个,因此它会以最后一个 -- 结束64-bit。

    • 3

相关问题

  • 知道任何适用于 Windows 的快速可编写脚本的 ftp 客户端吗?[关闭]

  • 如果 Windows 服务崩溃,如何自动重新启动它?

  • 无法安排任务(访问被拒绝)

  • 物理机重启时自动重启虚拟机(VMWare)

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve