PowerShell的:修改数组中的元素 [英] PowerShell: modify elements of array

查看:190
本文介绍了PowerShell的:修改数组中的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的cmdlet的获取对象返回为MyObject 的数组公共属性:

 公共类为MyObject {
    公共字符串的TestString =测试;
}

我希望用户无需编程技能,以便能够从阵列中的所有对象修改公共属性(如的TestString 在这个例子中)。
然后将修改后的数组供给到我的节省的对象到数据库中第二小命令

这意味着编辑code的语法必须尽可能简单。

它应该看起来有点像这样:

 >得到的对象|的foreach {$ _的TestString =为newValue。} |设置对象

我知道这是不可能的,因为<一href=\"https://social.technet.microsoft.com/forums/scriptcenter/en-US/a0a92149-d257-4751-8c2c-4c1622e78aa2/powershell-modifying-array-elements\"相对=nofollow> $ _刚刚返回该数组元素的副本。

所以你需要通过存取权限索引元素循环,然后再修改property.This得到真的很快很复杂的人是不熟悉编程。


是否有这样做的任何用户友好内置的方式吗?它不应该比一个简单的的foreach更复杂{=属性值}


解决方案

  

我知道这是不可能的,因为$ _刚刚返回该数组元素的副本(<一个href=\"https://social.technet.microsoft.com/forums/scriptcenter/en-US/a0a92149-d257-4751-8c2c-4c1622e78aa2/powershell-modifying-array-elements\" rel=\"nofollow\">https://social.technet.microsoft.com/forums/scriptcenter/en-US/a0a92149-d257-4751-8c2c-4c1622e78aa2/powershell-modifying-array-elements)


我觉得你错INTE preting在该线程的答案。

$ _ 确实通过枚举无论您当前迭代返回的值的本地副本 - 但是你仍然可以回到你的修改该值的副本(如<一个href=\"http://stackoverflow.com/questions/34166023/powershell-modify-elements-of-array#comment56079464_34166023\">pointed出在评论):

 获取对象|的foreach对象{
    #修改当前项目
    $ _。PROPERTYNAME =值
    #删除修改的对象到管道
    $ _
} |设置对象


在你需要修改对象的存储阵列(据称是不可能的)的情况下,可以使用相同的技术用新值覆盖数组:

  PS C:\\&GT; $ myArray的= 1,2,3,4,5
PS C:\\&GT; $ myArray的= $ myArray的|的foreach对象{
&GT;&GT;&GT; $ _ * = 10
&GT;&GT;&GT; $ _
&GT;&GT;&GT;}
&GT;&GT;&GT;
PS C:\\&GT; $ myArray的
10
20
三十
40
50



  

这意味着编辑code的语法必须尽可能简单。


值得庆幸的是,PowerShell是的非常的自省方面功能强大。你可以实现一个包装的功能,增加了 $ _; 语句的循环体的结束,如果用户忘记:

 函数添加-PsItem
{
    [CmdletBinding()]
    参数(
        [参数(强制性,ValueFromPipeline,ValueFromRemainingArguments)
        [psobject []] $ InputObject,        [参数(强制性)
        [脚本块] $工艺
    )    开始 {        $ InputArray = @()        #获取在脚本块的最后一条语句
        $端块= $ Process.Ast.EndBlock
        $ LastStatement = $ EndBlock.Statements [-1] .Extent.Text.Trim()        #检查,如果最后的语句是`$ _`
        如果($ LastStatement -ne'$ _'){
            #如果没有,添加它
            $工艺= [脚本块] ::创建({0}; $ _'-f $ Process.ToString())
        }
    }    过程{
        #收集所有的输入
        $ InputArray + = $ InputObject
    }    结束 {
        #管道输入的foreach对象与新的脚本块
        $ InputArray |的foreach对象-Process $过程
    }
}

现在用户可以这样做:

 获取对象|附加PsItem {$ _的TestString =为newValue。} |设置对象

ValueFromRemainingArguments 属性,还可以让用户输入提供无限作为参数值:

  PS C:\\&GT;附加PsItem {$ _ * = 10} 1 2 3
10
20
三十

,如果用户不使用与管道的工作,这可能是有用的

My cmdlet get-objects returns an array of MyObject with public properties:

public class MyObject{
    public string testString = "test";
}

I want users without programming skills to be able to modify public properties (like testString in this example) from all objects of the array. Then feed the modified array to my second cmdlet which saves the object to the database.

That means the syntax of the "editing code" must be as simple as possible.

It should look somewhat like this:

> get-objects | foreach{$_.testString = "newValue"} | set-objects

I know that this is not possible, because $_ just returns a copy of the element from the array.

So you'd need to acces the elements by index in a loop and then modify the property.This gets really quickly really complicated for people that are not familiar with programming.


Is there any "user-friendly" built-in way of doing this? It shouldn't be more "complex" than a simple foreach {property = value}

解决方案

I know that this is not possible, because $_ just returns a copy of the element from the array (https://social.technet.microsoft.com/forums/scriptcenter/en-US/a0a92149-d257-4751-8c2c-4c1622e78aa2/powershell-modifying-array-elements)

I think you're mis-intepreting the answer in that thread.

$_ is indeed a local copy of the value returned by whatever enumerator you're currently iterating over - but you can still return your modified copy of that value (as pointed out in the comments):

Get-Objects | ForEach-Object {
    # modify the current item
    $_.propertyname = "value"
    # drop the modified object back into the pipeline
    $_
} | Set-Objects


In (allegedly impossible) situations where you need to modify a stored array of objects, you can use the same technique to overwrite the array with the new values:

PS C:\> $myArray = 1,2,3,4,5
PS C:\> $myArray = $myArray |ForEach-Object {
>>>    $_ *= 10
>>>    $_
>>>}
>>>
PS C:\> $myArray
10
20
30
40
50


That means the syntax of the "editing code" must be as simple as possible.

Thankfully, PowerShell is very powerful in terms of introspection. You could implement a wrapper function that adds the $_; statement to the end of the loop body, in case the user forgets:

function Add-PsItem 
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory,ValueFromPipeline,ValueFromRemainingArguments)]
        [psobject[]]$InputObject,

        [Parameter(Mandatory)]
        [scriptblock]$Process
    )

    begin {

        $InputArray = @()

        # fetch the last statement in the scriptblock
        $EndBlock = $Process.Ast.EndBlock
        $LastStatement = $EndBlock.Statements[-1].Extent.Text.Trim()

        # check if the last statement is `$_`
        if($LastStatement -ne '$_'){
            # if not, add it
            $Process = [scriptblock]::Create('{0};$_' -f $Process.ToString())
        }
    }

    process {
        # collect all the input
        $InputArray += $InputObject
    }

    end {
        # pipe input to foreach-object with the new scriptblock
        $InputArray | ForEach-Object -Process $Process
    }
}

Now the users can do:

Get-Objects | Add-PsItem {$_.testString = "newValue"} | Set-Objects

The ValueFromRemainingArguments attribute also lets users supply input as unbounded parameter values:

PS C:\> Add-PsItem { $_ *= 10 } 1 2 3
10
20
30

This might be helpful if the user is not used to working with the pipeline

这篇关于PowerShell的:修改数组中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆