当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 使用 Import-Csv 在 PowerShell 中管理 CSV 文件

作者:精品下载站 日期:2024-12-14 20:50:46 浏览:17 分类:玩电脑

使用 Import-Csv 在 PowerShell 中管理 CSV 文件


PowerShell Export-Csv cmdlet 和 PowerShell Import-Csv cmdlet 允许管理员通过 foreach 循环导入 CSV,请使用 Export-Csv 附加 CSV 并将数组导出到 CSV 文件等等。

在本文中,您将了解许多可以使用 PowerShell 管理 CSV 的常见场景,例如:

  • 使用 PowerShell 读取 CSV 文件
  • 使用 PowerShell 保存 CSV 文件
  • 在运行 Export-CSV 之前格式化输出
  • 附加到 CSV
  • 将差异附加到现有文件
  • Export-CSV#TYPE 字符串

如果您不熟悉 CSV 文件的内部工作原理,它们是遵循标准格式的文本文件,用逗号分隔表中的值。您可以使用 Export-Csv cmdlet 在 PowerShell 中创建 CSV 文件,并将一个或多个对象通过管道传输到该文件。

以下命令查找前两个正在运行的进程,并将生成的对象传递给 Export-Csv cmdlet。然后,Export-Csv cmdlet 在系统驱动器的根目录(很可能C:\)中创建一个名为processes.csv的 CSV 文件。

PS51> Get-Process | Select-Object -First 2 | Export-CSV -Path "$env:SystemDrive\processes.csv"

现在用记事本打开processes.csv。您应该在顶部看到 "Name","SI","Handles","VM" 作为标题。您还将看到#TYPE System.Diagnostics.Process,现在可能没有多大意义。别担心,我们将在本文中介绍该字符串。

使用 Import-Csv 读取 CSV 文件

想要更多这样的提示吗?查看我的个人 PowerShell 博客。

PowerShell 有几个命令可让您读取文本文件。这些命令是 Get-ContentImport-Csv。从技术上讲,这两个 cmdlet 都以相同的方式读取文件。但 Import-Csv 更进一步。 Import-Csv 不仅了解文本文件,还了解 CSV 文件的底层结构。

由于 CSV 文件遵循特定架构,因此 Import-Csv 能够理解 CSV 架构。此 cmdlet 仅从磁盘读取文本文件,还将 CSV 文件中的行转换为 PowerShell 对象。

非 CSV 文件

通常,CSV 的数据是用逗号分隔的,但有时 CSV(但从技术上讲不是 CSV)的数据是用不同的分隔符分隔的。这些分隔符有时是制表符或分号。

如果您的 CSV 具有不同的分隔符,则可以使用 Delimiter 参数。此参数告诉 Import-Csv 不要查找逗号(默认情况下会这样做),而是查找另一个值。

例如,如果您有一个制表符分隔的文件,您可以像下面这样读取该文件:

PS51> Import-Csv -Path tab-separated-data.csv -Delimiter "`t"

添加标头

常见的 Import-Csv 参数是 Header。通过此参数,您可以指定由此 cmdlet 创建的对象的属性名称。

默认情况下,Import-Csv cmdlet 会将 CSV 文件的顶行视为标题。然后它会将这些值转换为每行(对象)的属性。但是,如果您的 CSV 文件没有标题行,则可以使用 Header 参数自行定义标题行。

Header 参数可防止 Import-CSV 使用第一行作为标题,还可以让您免去手动打开 CSV 文件自行添加标题的麻烦。

要演示此行为,请打开记事本并复制/粘贴下面的文本。该文本将表示一个三行两列的数据集。

a,1
b,2
c,3

将文本文件另存为 test.csv。不要忘记启用文件类型扩展名或用双引号将文件引起来,这样您就不会意外地将其保存为以 .csv.txt 结尾的文件!

现在,使用 Import-CSV 读取最近创建的不带 Header 参数的 CSV 文件并检查输出。

PS51> Import-Csv .\test.csv

a 1
---
b 2
c 3

请注意,它使用第一行作为对象属性。 A1 不是您想要的对象属性的“标签”。 Abc 是字母,而 12 3 是数字。您需要使用 Header 参数定义它们,如下所示:

PS51> Import-Csv .\test.csv -Header "Letter", "Number"

Letter Number
------ ------
a      1
b      2
c      3

使用 PowerShell 保存 CSV 文件

如果您需要从 PowerShell 对象创建或保存 CSV 文件,也可以采用其他方法。 Import-Csv cmdlet 将 CSV 文件“转换”为 PowerShell 对象,而 Export-Csv 则执行相反的操作。此 cmdlet 将 PowerShell 对象“转换”为 CSV 文件。

通过使用 Export-Csv 保存 CSV 文件,您可以稍后在其他系统中查看或使用该数据。

例如,我可以通过将 Get-Process 通过管道传输到 Export-Csv cmdlet 来保存计算机上的所有正在运行的进程。

PS51> Get-Process | Export-Csv -Path processes.csv

Export-Csv cmdlet 本质上很简单,但有一些问题需要注意。

在运行 Export-CSV 之前格式化输出

正如您在上面看到的,Export-Csv 本身会进行“原始”转换。它不添加任何特殊的富文本格式、添加任何颜色等。

最常见的问题之一是在导出到 CSV 之前尝试使输出看起来漂亮。许多用户在导出到 CSV 之前会尝试使输出看起来更好。但我要向你展示的是,这会让事情变得更糟。

您可以在 Microsoft Excel 中打开 CSV 并设置斜体、粗体、添加颜色和许多其他内容,但如果将文件另存为 CSV(而不是 Excel 工作簿),所有格式都将被删除。 CSV 文件根本不够“智能”。

回想一下,CSV 文件只是纯文本文件,其值由逗号(有时是制表符)分隔。 通过管道将 Import-Csv 传送到 Format-* PowerShell cmdlet 将无法按预期工作。 EM>

根据 Microsoft Export-Csv 文档:“在将对象发送到 Export-CSV cmdlet 之前不要对其进行格式化。如果 Export-CSV 接收格式化对象,则 CSV 文件包含格式属性而不是对象属性。”

为什么是这样?

打开 PowerShell 窗口并创建一些虚拟数据。让我们使用本文第一部分中介绍的 Get-Process 示例。但这一次,将输出分配给一个变量。然后,将这些进程对象通过管道传递给 Format-Table cmdlet。

PS51> $a = Get-Process
PS51> $a | Format-Table

[玩转系统] 使用 Import-Csv 在 PowerShell 中管理 CSV 文件

您可以看到使用Format-Table,您现在拥有干净的表格输出。

现在将此输出保存到另一个变量。

PS51> $b = $a | Format-Table

现在,使用 Get-Member 查看 $a$b 变量值的属性。此 cmdlet 将帮助您了解为什么这两个看似相似的对象不以相同的方式导出到 CSV 文件:

PS51> $a | Get-Member

[玩转系统] 使用 Import-Csv 在 PowerShell 中管理 CSV 文件

PS51> $b | Get-Member

[玩转系统] 使用 Import-Csv 在 PowerShell 中管理 CSV 文件

Get-Process 直接输出返回:TypeName: System.Diagnostics.Process,而 Format-Table 的输出则完全不同。它返回许多具有不同属性的不同类型。

如果您在控制台中查看 $a$b,输出将看起来相同。此行为是由于 PowerShell 的格式化系统造成的。

这如何影响 Export-Csv 的输出?

PS51> $b | Export-Csv | Format-Table

Export-Csv 按原样读取每个对象。当您将输出通过管道传输到 Format-* cmdlet 时,您正在更改 Export-CSV 接收的输入。这会影响保存到新 CSV 文件中的输出。

如果您要将输出通过管道传输到 Export-Csv cmdlet,请勿将输出通过管道传输到任何 Format-* cmdlet。

请记住,CSV 专注于数据,而不是格式。

附加到 CSV 文件

有时,您可能想要添加一个现有文件,而不是完全创建一个新文件。默认情况下,Export-Csv 将覆盖通过 Path 参数指定的任何文件。

如果您需要将数据附加到 CSV,请使用 Append 参数。

假设您有一个循环,希望将处理后的每个对象保存到 CSV 中。对于每次迭代,您都有一个想要保存到 CSV 文件的不同对象。由于您重复调用 Export-Csv,因此如果您不使用 Append 参数,它将覆盖该 CSV 文件。如果没有 Append 参数,您将只能获得 last 对象,这在大多数情况下不是所需的输出。

下面的示例查找前五个正在运行的进程。然后进入 PowerShell Import-Csv foreach 循环,并将 NameProductVersion 属性记录到 test.csv 一次归档一个。

Get-Process | Select-Object -First 5 | Foreach-Object {
    $_ | Select-Object Name, ProductVersion | Export-CSV -Path C:\test.csv -Append
}

如果不使用 Append 参数,您将看到 CSV 文件中仅显示第五个进程。

差异附加到 CSV 文件

可以使用 Export-Csv 仅将属性差异附加到现有 CSV 文件。这意味着,如果 CSV 行的列和要记录的对象不同,则继续追加它们。

要仅将差异附加到 CSV 文件,您需要同时使用 AppendForce 参数。根据 Microsoft 文档,“当 ForceAppend 参数组合时,包含不匹配属性的对象可以写入 CSV 文件。仅匹配的属性才会写入文件。不匹配的属性将被丢弃。”

为了进行演示,请创建一个具有两个属性的对象; 姓名年龄

PS51> $Content = [PSCustomObject]@{Name = "Johnny"; Age = "18"}

现在创建另一个具有 NameZip 属性的对象。

PS51> $OtherContent = [PSCustomObject]@{Name = "Joe"; Zip = "02195"}

每个对象都有不同的属性。

接下来,从第一个对象创建一个 CSV 文件,然后尝试将第二个对象附加到 CSV(不使用 Force 参数)。您会收到一个错误。

PS51> $Content | Export-CSV -Path .\User.csv -NoTypeInformation
PS51> $OtherContent | Export-CSV -Path .\User.csv -NoTypeInformation -Append

[玩转系统] 使用 Import-Csv 在 PowerShell 中管理 CSV 文件

但是,如果您使用 Force 参数,Export-Csv 将非常有效。

PS51> $OtherContent | Export-CSV -Path .\User.csv -NoTypeInformation -Append -Force

但是,您会注意到 CSV 文件中的 Zip 列已消失。小心使用Force。它可能无法提供预期的输出。

PS51> Import-Csv -Path .\User.csv

Name   Age
----   ---
Johnny 18
Joe

Export-CSV#TYPE 字符串

默认情况下,使用不带其他参数的 Export-CSV 会在 CSV 文件顶部包含一个 #TYPE 字符串。该字符串后跟接收到的 Export-Csv 对象类型。

#TYPE System.Diagnostics.Process

大多数时候,这个字符串在消耗输出时实际上并没有什么用处。仅当您需要维护属性和值所来自的对象类型时,才存在该字符串。

要删除此字符串,请使用 NoTypeInformation 参数。此参数会从 CSV 中完全删除该字符串。

请注意,从 PowerShell Core 开始,这不再是必需的。

概括

使用 Import-CSVExport-CSV PowerShell cmdlet 可让您轻松处理 CSV 文件。这是两个有用的 cmdlet,在处理对象和 CSV 文件时应经常使用它们。

我希望通过我在此展示的解释和示例,您将能够清楚地了解可以利用这些 cmdlet 为您带来好处的情况。

想要更多这样的提示吗?查看我的个人 PowerShell 博客。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯