如何通过powershell将文本文件的每一行保存为数组

How to save each line of text file as array through powershell

如果我有一个文本文件,C:\USER\Documents\Collections\collection.txt 包含以下信息:

collectionA.json
collectionB.json
collectionC.json
collectionD.json

我想知道如何通过 Powershell 将文本文件中的每一行存储为数组的元素,例如..

array arrayFromFile = new Array;
foreach(line x in collection.txt)
{
    arrayFromFile.Add(x);
}

..最终目标是执行以下操作:

foreach(string x in arrayFromFile)
{
    newman run x;
}

对于这个看似简单的问题,我深表歉意 - 我以前从未处理过 Powershell。

Get-Content命令returns文本文件中的每一行作为一个单独的字符串,所以会给你一个数组(只要你不使用-Raw参数; 这会导致所有行合并为一个字符串)。

[string[]]$arrayFromFile = Get-Content -Path 'C:\USER\Documents\Collections\collection.txt'

中,mklement0 提供了更多关于调用此命令时实际发生的事情的详细信息,以及如果您关心性能而不是便利性的替代方法。如果您有兴趣了解更多关于该语言的知识,而不是仅仅解决这个一次性要求,那么绝对值得一读。

补充

Get-Content, as a cmdlet, outputs objects one by one to the pipeline可用时.(请注意,即使在没有管道符号的情况下调用 cmdlet 也会涉及管道, |, 用于链接 多个 命令)。
在这种情况下,输出对象是输入文本文件的各个

如果您收集管道的输出对象,例如通过将其分配给变量 例如 $arrayFromFile 或在具有 (...):

的较大表达式的上下文中使用管道
  • PowerShell 自动创建的数组中捕获多个输出对象,类型为[object[]],
  • 但是如果只有一个输出对象,该对象被捕获原样没有 数组包装器)

但是,通常没有必要确保您总是收到数组,因为 PowerShell 在许多上下文中将 scalars(非集合的单个值)与 arrays(集合)相同,例如 foreach statements or when outputting a value to be enumerated to the pipeline, to be processed via the ForEach-Object cmdlet,例如;因此,无论输入文件包含多少行,以下命令都可以正常工作:

# OK - read all lines, then process them one by one in the loop.
# (No strict need to collect the Get-Content output in a variable first.)
foreach ($line in Get-Content C:\USER\Documents\Collections\collection.txt) {
  newman run $line
}

# Alternative, using the pipeline:
# Read line by line, and pass each through the pipeline, as it is being
# read, to the ForEach-Object cmdlet.
# Note the use of automatic variable $_ to refer to the line at hand.
Get-Content C:\USER\Documents\Collections\collection.txt |
  ForEach-Object { newman run $_ }

为了确保命令的输出总是一个数组,PowerShell 提供了@(...), the array-subexpression operator,它甚至可以包装单个-数组中的对象输出。

因此,PowerShell 惯用的解决方案 是:

$arrayFromFile = @(Get-Content C:\USER\Documents\Collections\collection.txt)

TheMadTechnician 指出您 也可以使用 [array] 来转换/类型约束管道输出作为 @(...) 的替代方法,这也会创建 [object[]]数组:

# Equivalent of the command above that additionally locks in the variable date type.
[array] $arrayFromFile = Get-Content C:\USER\Documents\Collections\collection.txt

通过使用 [array] $arrayFromFile = ... 而不是 $arrayFromFile = [array] (...),变量 $arrayFromFile 变为 type-constrained,这意味着它的数据类型被锁定在(而默认情况下,PowerShell 允许您随时更改变量的类型)。

[array] 是 John 的回答 [string[]] 中使用的 type-specific cast 的独立于命令的替代方法;您可以使用后者来强制跨数组元素使用统一类型,但这在 PowerShell[1] 中通常不是必需的 .

常规 PowerShell 数组的类型为 [object[]],它允许混合不同类型的元素,但任何给定元素仍然具有特定类型;例如,即使上面命令后 $arrayFromFile 的类型是 [object[]]$arrayFromFile[0] 的类型,即第一个元素,例如,是 [string](假设文件至少包含 1 行;使用 $arrayFromFile[0].GetType().Name).

验证类型

更快的选择:直接使用 .NET 框架

Cmdlet 和管道提供了高级的、潜在的内存限制功能,这些功能具有表现力和方便性,但它们可能

当性能很重要时,直接使用 .NET 框架类型是必要的,例如本例中的 [System.IO.File]

$arrayFromFile = [IO.File]::ReadAllLines('C:\USER\Documents\Collections\collection.txt')

请注意如何从类型名称中省略 System. 前缀。

  • 正如约翰的回答,这将 return 一个 [string[]] 数组。

  • 注意事项:

    • 注意 相对 路径,因为 .NET 通常与 PowerShell 有一个 不同 当前目录;要解决这个问题,总是传递绝对路径,在最简单的情况下,例如,"$PWD/collection.txt",最稳健的是[=126] =] "$((Get-Location -PSProvider FileSystem).ProviderPath)/collection.txt"

    • .NET 的默认编码为 UTF-8,而 Windows PowerShell 默认为“ANSI”编码, i.e.the 系统语言环境的遗留代码页; PowerShell Core (v6+),相比之下,也默认为 UTF-8。使用 Get-Encoding-Encoding 参数或接受编码实例的 .ReadAllLines() 重载来明确指定输入文件的字符编码。


[1] 通常,PowerShell 的隐式运行时类型转换无法提供与 C# 中相同的类型安全性。例如,[string[]] $a = 'one', 'two'; $a[0] = 42 不会 导致错误:PowerShell 只是悄悄地将 [int] 42 转换为字符串。

$array = Get-Content -Path @("C:\tmp\sample.txt")
foreach($item in $array)
{
 write-host $item 
}