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

How do I edit the values of imported CSV variable with PowerShell

下面的脚本是我导入 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]

这是输出,数据没有变化,狗的状态仍然是冗余。

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 属性 值的数组”,这是您最终用 $Animal_Farm.Status[1].

索引的内容

要寻址原始数组中基础项之一的属性,请直接在 $Animal_Farm 上使用索引运算符:

$Animal_Farm[1].Status

用概念信息补充

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

此功能也适用于方法,称为成员访问枚举,在 this answer.

中有更详细的解释

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

如果您在尝试为所有动物设置状态属性时尝试了$Animal_Farm.Status = 'Employed' ,你会得到一个 有点令人惊讶的 错误 ,说明集合 $Animal_Farm 没有 .Status 属性 .

  • 尽管有令人惊讶的错误消息(技术上 正确),但无法分配 a(根据定义集合的所有单个元素的给定 属性 的统一) 值是设计
  • 相比之下,通过成员访问枚举调用变异 方法 - 如果可用 - 可能的。
  • 有关详细信息,请参阅 this answer and GitHub issue #5271

如果您尝试通过索引 ([...]) 将 属性 值分配到数组中通过成员访问枚举 ($Animal_Farm.Status) 获得的值,例如$Animal_Farm.Status[1] = "Employed",那个 作业被 悄悄忽略了

  • 原因是 $Animal_Farm.Status return 是 属性 的数组 不再连接到它们来自的对象,虽然您可以通过分配给它的元素在技术上修改这个数组,修改后的数组只是在赋值语句之后丢弃 ,因为它没有在任何地方被捕获。
    简而言之:你错误地修改了一个临时数组

  • 相比之下,将索引应用于集合本身($Animal_Farm[1] 到 return 第二个 对象 存储在集合中) return 是一个 对象引用 .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] 从技术上讲,如果输入集合具有 两个或更多值,则 数组 值仅被 returned 个元素;对于 单个元素 集合,该元素的 属性 值按原样 return 编辑。换句话说:成员访问枚举的行为类似于 PowerShell pipeline;请参阅 and for examples of associated pitfalls, and GitHub issue #6802 以了解对这种可能令人惊讶的行为的讨论。