还记得我刚学会使用PowerShell的时候,那种兴奋和幸福感。终于找到了在Windows下一个强大的Shell(因为他叫Power Shell)。可以一边使用着熟悉的Windows桌面系统一边装X的Shell编程了。当我使用它来处理CSV时一个意外的发现,仿佛为我点亮了PowerShell的又一片地图。因为我发现每次不管处理什么样的CSV,最后它总能将每一行数据转化成一个方便处理的对象。就像JavaScript里面的Object可以动态添加属性一样。
接下来看看PSCustomObject的神奇。
初识PSCutomObject
假如你有一个CSV文件需要处理, 通过Import-Csv把它倒入内存中。
$csvdata=Import-Csv -Path C:\new_user_credentials.csv
看下这个$csvdata都有些什么数据呢?格式化一下
$csvdata | fl
是不是看起来很像是Javascript的Object对象,如果CSV文件里面有更多的列,那么对应的 $csvdata也会有更多的属性。
我们可以看下这个$csvdata到底是什么类型的
$csvdata.GetType()
获取某一条数据的某一个属性:
$csvdata.'User name'
admin
改变数据:
$csvdata.'User name'='root'
$csvdata.'User name'
root
$csvdata | Add-Member -MemberType NoteProperty -Name Status -Value "Processed" #添加处理结果
$csvdata
User name : root
Password :
Access key ID : AKIAUBW6TJDQAQ7GLWXY
Secret access key : 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
Console login link : https://278565964000.signin.aws.amazon.com/console
Status : Processed
数据处理好之后我们可以使用Export-Csv来把处理结果导出成csv文件
$csvdata | Export-Csv C:\new_user_credentials_processed.csv -NoTypeInformation -Encoding:UTF8
可以看到,导入内存中的CSV文件的每一条数据会被转化成一个PSCustomObject,而CSV文件的每一列会被转化成这个PSCustomObject的属性。这样我们就可以很方便的处理CSV数据了。
创建PSCustomObject
那么我们如何自己创建一个PSCutomObject呢?两种方法
第一种:当前较新版本推荐
$obj = [PSCustomObject]@{
Author = '树梢的鱼鱼'
Catalog = 'PowerShell'
Title = '我以前居然不知道PowerShell这么强大的[PSCustomObject]'
}
$obj | fl
# Author : 树梢的鱼鱼
# Catalog : PowerShell
# Title : 我以前居然不知道PowerShell这么强大的[PSCustomObject]
@{
Author = '树梢的鱼鱼'
Catalog = 'PowerShell'
Title = '我以前居然不知道PowerShell这么强大的[PSCustomObject]'
}
这是PowerShell里面创建Hashtable的方法。然后使用[PSCutomObject]来强制转换。
第二种:使用New-Object, 适用于早期的PowerShell脚本
$obj = New-Object -TypeName PSObject -Property @{
Author = '树梢的鱼鱼'
Catalog = 'PowerShell'
Title = '我以前居然不知道PowerShell这么强大的[PSCustomObject]'
}
$obj | fl
# Author : 树梢的鱼鱼
# Catalog : PowerShell
# Title : 我以前居然不知道PowerShell这么强大的[PSCustomObject]
关于多种保存PSCustomObject到文件的方法,除了上面说的Export-CSV还可以参考 The many ways to read and write to files
操作PSCustomObject的属性
下面的有些方法不仅限于PSCustomObject对象。参考原文
添加属性 (适用于所有的PowerShell对象)
$csvdata | Add-Member -MemberType NoteProperty -Name Status -Value "Processed" #添加处理结果
删除属性 (适用于所有的PowerShell对象,但仅适用于动态添加的属性)
$obj | fl #删除之前
Author : 树梢的鱼鱼
Catalog : PowerShell
Title : 我以前居然不知道PowerShell这么强大的[PSCustomObject]
$obj.psobject.Properties.Remove("Author")
$obj | fl #删除之前
Catalog : PowerShell
Title : 我以前居然不知道PowerShell这么强大的[PSCustomObject]
列举所有属性 (适用于所有的PowerShell对象)
$obj | gm -Type NoteProperty
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Catalog NoteProperty string Catalog=PowerShell
Title NoteProperty string Title=我以前居然不知道PowerShell这么强大的[PSCustomObject]
动态访问属性 (适用于所有的PowerShell对象)
$csvdata
User name : root
Password :
Access key ID : AKIAUBW6TJDQAQ7GLWXY
Secret access key : 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
Console login link : https://278565964000.signin.aws.amazon.com/console
Status : Processed
$name="User name"
$csvdata.'User name'
root
$csvdata.$name #这个使用方法使得PowerShell在某些特定的场景下使用特别方便,比如使用反射的方式来访问对象
root
添加一个方法
$ScriptBlock = {
$hashtable = @{}
foreach( $property in $this.psobject.properties.name )
{
$hashtable[$property] = $this.$property
}
return $hashtable
}
$memberParam = @{
MemberType = "ScriptMethod"
InputObject = $csvdata
Name = "ToHashtable"
Value = $scriptBlock
}
Add-Member @memberParam
$csvdata | gm
这在某些地方是特别有用的,比如我们某个对象的属性有更新我们想把这个更新推送到服务器端,并且为了减少网络开销我们希望尽可能少的传输数据。那么只更新那些被修改了的字段就显得很有必要,那么我们完全可以添加一个动态方法或者熟悉来记录那些属性被修改了,然后只更新这些被修改了的字段。
当然这只是一个思路,并且在工作中曾经使用过类似的方法。具体如何去实现希望读者发挥你的想象力。
总结
使用PSCustomObject让我们可以在PowerShell中很方便的处理和交换数据。并且结合使用Add-Member, Get-Member, ConvertFrom-Json, ConvertTo-Json, Import-CSV, Export-CSV等可以让PowerShell发挥异常强大的作用。你要悄悄学PowerShell然后惊艳所有人~~~。