当我的命令的第一个词是一个被扩展的变量时 Powershell 错误

标签 powershell

我想测试我正在编写的一个 powershell 脚本,其中包含一个我不想实际发生的带有副作用的命令。

在 bash 中,我可以写

> DO_OR_ECHO=$([ "$MY_DEBUG_FLAG" ] && echo 'echo' || echo)

> $DO_OR_ECHO my_dangerous_command args

但尝试在 powershell 中执行类似的构造似乎不起作用,即使我对其进行了硬编码也是如此。

> $DO_OR_ECHO='echo'

> $DO_OR_ECHO my_dangerous_command args

Unexpected token 'my_dangerous_command' in expression or statement.

我做错了什么?有更好的方法吗?我想要一个基于 bool 值的构造,它要么执行命令,要么简单地打印它(以便我可以看到被执行的内容)。

最佳答案

使用函数:

function doOrEcho() {
  $cmdLine = $Args
  if ($MY_DEBUG_FLAG) { # echo
    "$cmdLine"
  } else {                # execute
    # Split into command (excecutable) and arguments
    $cmd, $cmdArgs = $cmdLine
    if ($cmdArgs) {
      & $cmd $cmdArgs
    } else {
      & $cmd
    }
  }
}

然后按如下方式调用它:

doOrEcho my_dangerous_command args

限制:

  • 仅适用于调用外部程序,不适用于 PowerShell cmdlet 或函数。

    • 将数组 ($cmdArgs) 的元素作为单个 参数传递给外部程序是一项名为 splatting 的 PowerShell 技术。 ;见this answer了解更多信息,其中还指出了一般警告,即空字符串不能按原样作为参数传递,无论是直接传递还是作为用于展开的数组的一部分传递。
  • 在您的 Bash 解决方案中,回显命令不会反射(reflect)扩展参数的原始和/或必要引用,所以参数边界可能会丢失。


为了演示它(在 PowerShell Core 中调用 ls Unix 实用程序):

# Default behavior: *execute* the command.
PS> doOrEcho ls -1 $HOME
# ... listing of files in $HOME folder, 1 item per line.

# With debug flag set: only *echo* the command, with arguments *expanded*
PS> $MY_DEBUG_FLAG = $true; doOrEcho ls -1 $HOME
ls -1 /home/jdoe  # e.g.

Kory Gill指出 PowerShell 有 -WhatIf common parameter其目的是在不实际执行操作的情况下预览操作。

但是,-WhatIf 不是手头任务的正确解决方案:

  • 只有 cmdlet 和高级函数可以实现此参数(基于 PowerShell 提供的功能)- 这样做比上面的简单函数需要更多的努力。

  • -WhatIf 背后的意图是显示命令将对哪些数据 进行操作/它将对系统,而上述函数背后的意图是回显命令本身

    • 例如,Remove-Item foo.txt -WhatIf 会显示如下内容:
      假设:在目标“C:\tmp\foo.txt”上执行“删除文件”操作。
  • 虽然在这个用例中您在技术上仍然可以使用 -WhatIf,但是您必须临时使用 -WhatIf 来打开回显 ( doOrEcho -WhatIf ...) 或将 $WhatIfPreference 首选项变量设置为 $true - 但这样做会影响所有 在设置变量时支持 -WhatIf 的 cmdlet 和函数;此外,-WhatIf 输出是冗长的,如上所示。

可以说,PowerShell 的通用命令调用 cmdlet Invoke-Command 应该像上面的函数一样支持 -WhatIf,但它不支持。

关于当我的命令的第一个词是一个被扩展的变量时 Powershell 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55066054/

相关文章:

arrays - 使用数组和脚本 block 安装多个应用程序的 Powershell 脚本

powershell - 表达式或语句 powershell 中的意外标记 'if'

html - 在字符串 (PowerShell) 中转义 HTML 特定字符的最佳方法是什么?

scripting - PowerShell 脚本第一次失败但第二次有效

Powershell 内存使用 - 贵吗?

powershell - Powershell如何在字符串和 double 之间进行比较?

xml - 嵌套的 XML Powershell

powershell - 将单个文件复制到多个目录[如果有则覆盖]

function - PowerShell更改返回对象的类型

powershell - 从 Powershell ISE 运行脚本时如何绕过执行策略