如何使用PowerShell编辑导入的CSV变量的值



下面的脚本是我导入CSV文件,尝试编辑其中一个值,然后检查该值的示例。

$Animal_Farm = Import-CSV "Test.csv"
Echo "The Data"
$Animal_Farm
Echo "`n`n`n"
Echo "Dog's Status"
$Animal_Farm.Status[1]
Echo "`n`n`n"
Echo "Updating Dog's Status to Employed"
$Animal_Farm.Status[1] = "Employed"
Echo "`n`n`n"
Echo "Dog's Status"
$Animal_Farm.Status[1]

这是输出,数据不变,Dog的状态仍然是冗余。

The Data
Animal Ocupation    Status   
------ ---------    ------   
Cat    Construction Employed 
Dog    Professional Redundant
Rat    GP           Employed 


Dog's Status
Redundant


Updating Dog's Status to Employed


Dog's Status
Redundant

如何编辑导入的数据?我的计划是将修改后的数据馈送到JSON文件中。

这是CSV文件内容

Animal,Ocupation,Status
Cat,Construction,Employed
Dog,Professional,Redundant
Rat,GP,Employed

$Animal_Farm包含一个对象数组,每个对象都有一个Status属性。

当您要求PowerShell解析$Animal_Farm.Status时,PowerShell将转到";嗯,$Animal_Farm数组没有Status属性,让我根据数组中每个项的Status属性值创建一个新数组",这就是你最终用CCD_ 7索引的内容。

要处理原始数组中某个底层项的属性,请直接在$Animal_Farm上使用索引运算符:

$Animal_Farm[1].Status

用概念信息补充Mathias R.Jessen的有用答案:

正如Mathias所说,访问对象($Animal_Farm(的集合(数组(上的属性(.Status(会自动返回数组[1]中该集合的元素的属性值(假设集合本身没有此名称的属性,在这种情况下,后者优先(。

此功能也适用于方法,称为成员访问枚举,在本答案中有更详细的解释。

成员访问枚举不支持分配给属性,但是:

如果您在尝试为所有动物设置状态属性时尝试了类似$Animal_Farm.Status = 'Employed'的操作,则会出现有点令人惊讶的错误,说明集合$Animal_Farm没有.Status属性。

  • 尽管出现了令人惊讶的错误消息(从技术上讲是正确的(,但无法将(根据定义统一(值分配给集合中所有单个元素的给定属性,这是设计上的
  • 相比之下,通过成员访问枚举(如果可用(调用一个可变的方法是可能的
  • 有关更多信息,请参阅此答案和GitHub第5271期

如果您试图通过索引([...](将属性值分配到通过成员访问枚举($Animal_Farm.Status((例如$Animal_Farm.Status[1] = "Employed"(获得的值数组中,则将悄悄忽略该分配

  • 原因是$Animal_Farm.Status返回一个属性的数组,这些值不再与它们来自的对象连接,虽然从技术上讲,您可以通过向其元素赋值来修改此数组,但修改后的数组在赋值语句后会被丢弃,因为它不会在任何地方捕获
    简而言之:您错误地修改了临时数组

  • 相反,将索引应用于集合本身($Animal_Farm[1]返回存储在集合中的第二个对象(会返回的对象引用,然后可以有效地修改其.Status属性($Animal_Farm[1].Status = "Employed"(


简化示例

# Create a 2-element sample array.
$animals = [pscustomobject] @{ Animal = 'Cat'; Status = 'Employed' },
[pscustomobject] @{ Animal = 'Dog'; Status = 'Redundant' } 

# Trying to set the status of ALL animals via member-access enumeration
# CAUSES AN ERROR, because it isn't supported:
#     InvalidOperation: The property 'Status' cannot be found on this object. [...]
$animals.Status = 'Employed'    # !! ERROR

# Trying to set the status of ONE animal via member-access enumeration is
# QUIETLY IGNORED:
#  * What is being modified is a *temporary array* of property values.
#  * Therefore, $animals.Status[1] is still 'Redundant' after this statement.
$animals.Status[1] = 'Employed' # !! QUIETLY IGNORED
# OK: Avoid member-access enumeration, and index directly into the collection
#     to get the animal object of interest, then set its property:
$animals[1].Status = 'Employed' # OK

[1]从技术上讲,只有当输入集合具有两个或多个元素时,才会返回值的数组;对于单个元素集合,该元素的属性值将按原样返回。换句话说:成员访问枚举的行为类似于PowerShell管道;请参阅这个答案和这个答案,了解相关陷阱的示例,以及GitHub第6802期关于这种可能令人惊讶的行为的讨论

最新更新