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

JOb*_*loh 5 arrays powershell file-io line cmdlet

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

collectionA.json
collectionB.json
collectionC.json
collectionD.json
Run Code Online (Sandbox Code Playgroud)

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

array arrayFromFile = new Array;
foreach(line x in collection.txt)
{
    arrayFromFile.Add(x);
}
Run Code Online (Sandbox Code Playgroud)

..最终目标是:

foreach(string x in arrayFromFile)
{
    newman run x;
}
Run Code Online (Sandbox Code Playgroud)

我为这个看似简单的问题道歉 - 我以前从未处理过Powershell.

mkl*_*nt0 13

为了补充JohnLBevan的有用答案:

Get-Content作为cmdlet,当对象可用时,对象逐个输出到管道.(请注意,即使没有管道符号,也会在调用cmdlet时涉及管道|,用于链接多个命令).
在这种情况下,输出对象是输入文本文件的各.

如果收集管道的输出对象,例如通过将其分配给变量(例如,$arrayFromFile或者通过在较大表达式的上下文中使用管道)(...):

  • PowerShell的捕获多个在输出对象自动创建的数组,类型[object[]],
  • 但是如果只有一个输出对象,则按原样捕获该对象(没有数组包装器)

为了确保管道的输出始终是一个数组,PowerShell提供@(...)了一个array-subexpression运算符,它甚至可以包装数组中的单个对象输出.

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

$arrayFromFile = @(Get-Content C:\USER\Documents\Collections\collection.txt)
Run Code Online (Sandbox Code Playgroud)

但是,通常没有必要确保始终接收数组,因为PowerShell将标量(非集合的单个值)与许多上下文中的数组(集合)相同,例如在foreach语句中或输出值时被列举到管道.

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
Run Code Online (Sandbox Code Playgroud)

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

[Array]是John的答案中使用的特定类型的演员的独立于命令的替代方案[string[]]; 你可以使用后者来强制在数组的元素中使用统一类型,但这在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')
Run Code Online (Sandbox Code Playgroud)

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

  • 在John的回答中,这将返回一个[string[]]数组.

  • 警告:

    • 注意相对路径,因为.NET通常具有与PowerShell 不同的当前目录; 解决这个问题,总是传递绝对路径,例如"$PWD/collection.txt".

    • .NET的默认编码是UTF-8,而Windows PowerShell默认为"ANSI"编码,系统区域设置的遗留代码页; 相比之下,PowerShell Core默认为UTF-8.使用Get-Encoding-Encoding参数或.ReadAllLines()接受一个编码实例来显式地指定输入文件的字符编码过载.


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

  • 非常感谢您的精彩回答。我测试了.NET 方法,速度快了 10 倍以上。113k 行花费了:0.0933256 秒,使用 Get-Content 花费了:1.1153968 秒。 (2认同)

Joh*_*van 12

Get-Content命令将文本文件中的每一行作为单独的字符串返回,因此将为您提供一个数组(只要您不使用该-Raw参数;这会导致所有行组合成一个字符串).

[string[]]$arrayFromFile = Get-Content -Path 'C:\USER\Documents\Collections\collection.txt'
Run Code Online (Sandbox Code Playgroud)

他的出色答案中,mklement0提供了更多关于调用此命令时实际情况的详细信息,以及如果您担心性能而非方便性的替代方法.如果你有兴趣学习更多关于语言的知识而不仅仅是解决这个问题,那么绝对值得一读.


Job*_*mes 5

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

Run Code Online (Sandbox Code Playgroud)

  • 展示完整示例的好主意。请注意,“-Path”参数周围不需要“@(...)”,“-Path C:\tmp\sample.txt”即可。PowerShell 中的数组值参数始终也接受标量值(即使有多个值,如“-Pathsample1.txt,sample2.txt”也可以)。 (2认同)