2

下面的脚本是我导入 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 的状态仍然是 Redundant。

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
4

2 回答 2

3

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

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

此功能也适用于方法,称为成员枚举,并在此答案中进行了更详细的说明。

成员枚举不支持分配properties,但是:

如果您尝试所有动物设置状态属性,您会得到一个有点令人惊讶$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 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 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 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以讨论这种可能令人惊讶的行为。

于 2021-07-14T12:57:10.903 回答
3

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

当您要求 PowerShell 解析$Animal_Farm.Status时,PowerShell 会出现“嗯,$Animal_Farm数组没有Status属性,让我根据数组Status中每个项目的属性值创建一个新数组”,这就是您最终使用$Animal_Farm.Status[1].

要解决原始数组中基础项之一的属性,请直接使用索引运算符$Animal_Farm

$Animal_Farm[1].Status
于 2021-07-14T11:45:27.903 回答