【问题标题】:Strange redirect in Batch/Powershell polyglot批处理/Powershell 多语言中的奇怪重定向
【发布时间】:2017-10-08 12:50:09
【问题描述】:

在尝试重写批处理文件时,我正在研究使用 powershell 的可能性。我遇到的主要问题是 .ps1 文件默认情况下不可执行。我找到了一个解决方案here,我将在下面复制它,但我对第一行的语法感到非常困惑:

<# : batch script
@echo off
setlocal
cd %~dp0
powershell -executionpolicy remotesigned -Command "Invoke-Expression $([System.IO.File]::ReadAllText('%~f0'))"
endlocal
goto:eof
#>
# here write your powershell commands...

这是我从测试中了解到的:

  • &lt;#: 之间的空格是必需的,但可以有多个。
  • 它还可以预先包含一个数字 0-9,例如 3&lt;# :,这让我怀疑重定向和标签存在一些奇怪之处。
  • 冒号后面的文本被忽略且没有必要
  • 如果我在它之前添加一个命令,例如git &lt;# : batch script,shell 会显示它试图评估git : batch script 0&lt;# 并且找不到指定的文件
  • # 更改为有效的文件名会使投诉消失(自然)
  • 尝试在交互式会话中运行该行实际上会导致它抱怨无法找到指定的文件,但从脚本运行它(即使它是 .cmd 文件中的唯一行)静默成功

最后一个项目符号是我想要弄清楚的部分。环境有什么不同?我的理解是,问题的一部分是运行一个 bat 文件被解析,就好像每一行都是手动输入的。为什么通过脚本调用 # 时不抱怨是无效文件?

【问题讨论】:

  • 你确定这不是多行注释,用于显示“旧”批处理文件代码?

标签: windows powershell batch-file cmd


【解决方案1】:

"...运行一个 bat 文件会被解析为每一行都是手动输入的。"

不,命令行和批处理文件之间的解析器规则有时不同,在这种情况下,差异很关键。

它抱怨# 在命令行中是一个无效文件,而不是在批处理文件中,因为&lt;# : 构造(对于批处理解析器)只是一个重定向的标签。与您在goto :labelcall :label 中使用的标签相同。

这意味着重定向不是在批处理文件中执行的,因为与重定向关联的“命令”是一个标签,而是在命令行中执行的,因为您不能在命令行中拥有标签。

【讨论】:

  • 是否有任何文件显示这一点?我仍然不完全确定为什么存在差异,因为我似乎可以在交互式会话中创建标签?
  • @MattSoucy,如果你从命令行使用类似:label 的东西,你将没有标签(你不能给它gotocall),而是一个null命令 (我必须给它一个名字)只要第一个非空白/非分隔符字符是一个冒号。您可以使用:label &lt;filefile 存在与否)它会“工作”(空命令),但如果您编写&lt;file :labelfile 存在)重定向会更改解析,您将得到一个:label 的错误不能作为命令处理。批处理文件中只有 标签
【解决方案2】:

诀窍是您需要一个有效的结构,powershell 和批处理。
仅对于 powershell,&lt;# 对打开多行注释很重要。

对于批处理,您需要一些有效代码,但在 echo on 状态下不可见。
因此,在这种情况下,冒号是完美的,因为即使使用echo on,也不会显示标签行。

你可以看到解析器的结果,当你用REM替换冒号时。

<# REM Batch script

输出:

c:\Temp>REM batch script 0<#

# 是一个有效的文件名,但文件本身永远不会被访问。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-22
    • 2021-12-20
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 2018-07-09
    相关资源
    最近更新 更多