【问题标题】:How to convert $args to a string and execute?如何将 $args 转换为字符串并执行?
【发布时间】:2019-01-03 18:06:53
【问题描述】:

我想传递给脚本的所有参数并执行。

例如,给定execute.ps1 脚本:

Invoke-Expression $($args[0])

我可以跑:

.\execute.ps1 hostname
myhostname

与此脚本的两个参数相同:

Invoke-Expression "$($args[0]) $($args[1])"

并通过以下方式执行它:

.\execute.ps1 echo foo
foo

如何使脚本通用以支持未知数量的参数?

例如:

.\execute.ps1 echo foo bar buzz ...

我尝试了以下失败的组合:

Invoke-Expression $args

Invoke-Expression:无法将“System.Object[]”转换为参数“Command”所需的类型“System.String”。不支持指定的方法。


Invoke-Expression [system.String]::Join(" ", $args)

Invoke-Expression:找不到接受参数“System.Object[]”的位置参数。


Invoke-Expression $args.split(" ")

Invoke-Expression:无法将“System.Object[]”转换为参数“Command”所需的类型“System.String”。不支持指定的方法。


Invoke-Expression [String] $args

Invoke-Expression:找不到接受参数“System.Object[]”的位置参数。

【问题讨论】:

  • 您不能只为您的 .ps1 文件指定输入参数吗?
  • 我需要动态的,不知道有多少参数。当我使用 aws-ecr-login.ps1 登录到不同的 AWS 角色并执行 docker 命令时,我有一个用例。然后我想允许用户将参数传递给脚本,所以它在登录过程之后被调用,但可能有未知数量的参数。用例并不重要,因此我尽可能简化了示例。

标签: powershell invoke-command


【解决方案1】:

我推荐Bill_Stewart's answer 以避免命令本身(第一个参数)有空格的问题。但即使有这个答案,您也必须小心单独引用参数,并注意that itself itself a complicated thing


你可以这样做:

 Invoke-Expression "$args"

默认情况下,以这种方式转换为字符串会用空格连接它(从技术上讲,用默认的输出字段分隔符连接它,即$OFS 的值,默认为空格)。

您也可以按照韦恩的回答进行手动连接。

【讨论】:

  • @Bill_Stewart 是的,但其他答案也不会。这种传递参数的方法需要调用者理解 PowerShell 将解释第一组引号,并在必要时重复引用execute.ps1 echo '"hello there"'。任何 shell 都是如此,不是吗?
  • 我不推荐这个答案,因为Invoke-Expression is considered harmful.
  • @Bill_Stewart 我已经更新了我的答案,但是那篇文章中的大部分内容也没有单独使用& 来解决;当然,注入角度只能通过不尝试执行参数来解决。
【解决方案2】:

我的建议是避免使用Invoke-Expression,而是使用&。示例:

$command = $args[0]
$params = ""
if ( $args.Count -gt 1 ) {
  $params = $args[1..$($args.Count - 1)]
}
& $command $params

当然,包含空格的参数仍然需要包含嵌入引号。

【讨论】:

  • 如果$command 是一个函数,它将只接收一个参数$params,它是一个数组,而不是它所期望的参数数组。为了避免它,这样写最后一行:& $command @params
  • 问题是关于数组的第一个元素何时是命令名,而后面的元素是参数。 (这就是为什么我的答案是这样写的。)
【解决方案3】:

$args 是由输入创建的以空格分隔的字符串数组

   Invoke-Expression -Command "$($args -join " ")"

用空白字符重新加入它,并将它作为字符串传递给 invoke-expression 对我有用。

【讨论】:

  • 也可以手动更简单一点:-Command ($args -join ' ')
  • 我倾向于在我的脚本中获得一点“转换为字符串”的感觉。我永远记不起什么时候起作用的所有规则;)
  • 执行子表达式似乎无害(除非它是一个非常大的循环,否则任何性能影响都可以忽略不计),但是subexpressions have some bugs that you may never run into, but really suck 所以我在不需要它们时尽量避免它们。
  • 如果 $args 中有数组(例如,参数之一是 1,2,3),它们将作为字符串“System.Object[]”传递,因为 $args 中的每个项目都被转换在连接之前使用 ToString() 来字符串,而 Array.ToString() 会丢失数据。
猜你喜欢
  • 1970-01-01
  • 2021-12-30
  • 2020-08-23
  • 2011-12-17
  • 2018-05-09
  • 1970-01-01
  • 2018-12-05
  • 2021-06-14
  • 2019-02-15
相关资源
最近更新 更多