Powershell将字符串重新计算为数组

6l7fqoea  于 2022-12-13  发布在  Shell
关注(0)|答案(1)|浏览(139)

我有许多这样的字符串,我希望powershell重新求值\转换为数组(就像如果你只是在伊势中编写相同的代码而不使用单引号会发生什么)。
$String = '@("a value","b value","c value")'
有没有比从字符串中剥离'@' & '()'并使用-split更简单的方法呢?
提前感谢你的帮助。

pkbketx9

pkbketx91#

只要 string 包含有效的表达式,就可以使用[scriptblock]::Create(..)方法:

$String = '@("a value","b value","c value")'
& ([scriptblock]::Create($String))

Invoke-Expression也可以工作,在这种情况下,基本上是相同的。
然而,正如zett42在评论中指出的,脚本块的一个很好的特性是,我们可以使用它们来验证CheckRestrictedLanguage method是否禁止执行任意代码。
在下面的示例中,Write-Host是允许的命令,仅包含 'Write-Host "Hello world!"' 的字符串不会引发异常,但是,$allowedCommands中未列出的赋值语句或任何其他命令将引发异常,并且脚本块将不执行

$String = @'
Write-Host "Hello world!"
$stream = [System.Net.Sockets.TcpClient]::new('google.com', 80).GetStream()
'@

[string[]] $allowedCommands  =  'Write-Host'
[string[]] $allowedVaribales =  ''

try {
    $scriptblock = [scriptblock]::Create($String)
    $scriptblock.CheckRestrictedLanguage(
        $allowedCommands,
        $allowedVaribales,
        $false # Argument to allow Environmental Variables
    )
    & $scriptblock
}
catch {
    Write-Warning $_.Exception.Message
}

另一种方法是在ConstrainedLanguage模式下用Runspace运行表达式。

function Invoke-ConstrainedExpression {
    [CmdletBinding(DefaultParameterSetName = 'ScriptBlock')]
    param(
        [Parameter(ParameterSetName = 'Command', Mandatory, ValueFromPipeline)]
        [string] $Command,

        [Parameter(ParameterSetName = 'ScriptBlock', Mandatory, Position = 0)]
        [scriptblock] $ScriptBlock,

        [Parameter()]
        [Management.Automation.PSLanguageMode] $LanguageMode = 'ConstrainedLanguage'
    )

    process {
        try {
            $null = $PSBoundParameters.Remove('LanguageMode')
            # bare minimum for the session state
            $iss = [initialsessionstate]::CreateDefault2()
            # set `ContrainedLanguage` for this session
            $iss.LanguageMode = $LanguageMode
            # create the PS Instance and add the expression to invoke
            $ps = [powershell]::Create($iss).AddScript.Invoke($PSBoundParameters.Values)
            # invoke the expression
            [Collections.Generic.List[object]] $stdout = $ps.Invoke()
            $streams = $ps.Streams
            $streams.PSObject.Properties.Add([psnoteproperty]::new('Success', $stdout))
            $streams
        }
        finally {
            if($ps) { $ps.Dispose() }
        }
    }
}

现在我们可以使用约束语言测试表达式:

Invoke-ConstrainedExpression {
    Write-Host 'Starting script'
    [System.Net.WebClient]::new().DownloadString($uri) | iex
    'Hello world!'
}

输出如下所示:

Success     : {Hello world!}
Error       : {Cannot create type. Only core types are supported in this language mode.}
Progress    : {}
Verbose     : {}
Debug       : {}
Warning     : {}
Information : {Starting script}

开发博客文章:PowerShell Constrained Language Mode有一些不错的信息,绝对值得一读。

相关问题