补充JohnLBevan's helpful answer:
Get-Content,作为 cmdlet,将对象一个一个输出到pipeline,当它们可用时 .(请注意,即使在没有管道符号 | 的情况下调用 cmdlet 以链接多个命令时,也会涉及管道)。
在这种情况下,输出对象是输入文本文件的各个 行。
如果您收集管道的输出对象,例如通过将其分配给变量(例如$arrayFromFile)或使用管道在(...) 的更大表达式的上下文中:
- PowerShell 在一个自动创建的数组中捕获多个输出对象,类型为
[object[]],
- 但如果只有一个输出对象,则按原样捕获该对象(没有数组包装)
但是,通常没有必要确保您始终收到 数组,因为 PowerShell 处理 标量 em>(不是集合的单个值)在许多上下文中与 arrays(集合)相同,例如在foreach 语句中或在输出要枚举到管道的值时,例如,通过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 变为类型受限,这意味着它的数据类型被锁定(而默认情况下,PowerShell 允许您更改类型任何时候的变量)。
[array] 是 John 的答案 [string[]] 中使用的 type-specific 强制转换的与命令无关的替代方案;您可以使用后者来强制在数组元素中使用统一类型,但这在 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. 前缀是如何从类型名称中省略的。
[1] 通常,例如,PowerShell 的隐式运行时类型转换无法提供与 C# 相同的类型安全性。例如,[string[]] $a = 'one', 'two'; $a[0] = 42 不会 导致错误:PowerShell 只是悄悄地将 [int] 42 转换为字符串。