我想测试我正在编写的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.
我在做什么错?有更好的方法吗?我想要一种基于布尔值的构造,该构造要么执行命令,要么简单地打印命令(以便我可以看到将执行的 )。
答案 0 :(得分:2)
使用函数:
function doOrEcho() {
$cmdLine = $Args
if ($MY_DEBUG_FLAG) { # echo
"$cmdLine"
} else { # execute
# Split into command (excecutable) and arguments
$cmd, [string[]] $cmdArgs = $cmdLine
if ($cmdArgs) {
& $cmd @cmdArgs
} else {
& $cmd
}
}
}
然后按如下所示调用它:
doOrEcho my_dangerous_command args
限制:
仅适用于对外部程序 的调用,不适用于PowerShell cmdlet或函数。
与您的Bash解决方案一样,回显的命令不会反映扩展参数的原始和/或必要的引用,因此参数界限可能会丢失。
进行演示(使用对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
的目的是显示命令将对哪些 data 进行操作/它将对系统进行哪些更改。上面功能的目的是回显命令本身。
Remove-Item foo.txt -WhatIf
将显示以下内容:What if: Performing operation "Remove File" on Target "C:\tmp\foo.txt".
尽管从技术上讲,您仍然可以使用-WhatIf
,但是您要么必须使用-WhatIf
即席打开回显(doOrEcho -WhatIf ...
)要么进行设置$WhatIfPreference
的{{1}}首选项变量-但这样做会影响 all 所有cmdlet和在设置变量时支持$true
的函数;另外,-WhatIf
的输出比较罗word,如上所示。
可以说,-WhatIf
是PowerShell的通用命令调用cmdlet,它应像上面的函数中一样支持Invoke-Command
,但不支持。
Splatting是一种技术,它允许您通过存储在变量中的哈希表或数组将参数传递给命令,然后用-WhatIf
而不是@
进行引用一个论点。
对于外部程序,只有 array 技术才有意义,并且-除了一个例外-您甚至可以按原样传递数组 -{以{1}}代替$
-达到相同的效果。
该异常是特殊的停止解析符号 $argumentArray
,它告诉PowerShell不要像往常一样解析其余的参数,而是按原样传递它们-未扩展,除了扩展@argumentArray
样式的变量引用(例如%USERNAME%。
只有喷溅语法(--%
)才能识别cmd.exe
符号。
但是,使用语法-@argumentArray
或--%
-为空字符串的参数(例如$argumentArray
或{{1 }})不能正确传递 ,因为PowerShell会简单地删除,这会破坏命令。
但是,这种情况也会随着传递 direct 参数而发生,并且是Windows PowerShell v5.1 / PowerShell Core 6.2.0及更高版本中PowerShell的固有限制(请参见this GitHub issue)。
例如,以下命令从@argumentArray
开始工作,但是由于参数为空而无法从PowerShell中断:
''