PowerShell:将整个文本文件内容存储在变量中

163

我想使用PowerShell将文本文件的全部内容(包括可能存在或不存在的尾随空行)存储在变量中。我还想知道文本文件中的总行数。最有效的方法是什么?

6个回答

258

顺便说一下,在PowerShell 3.0中,你可以使用新的Raw开关,使用Get-Content命令:

$text = Get-Content .\file.txt -Raw 

5
这应该是被接受的答案。顺便说一下,我相当确定Get-Content在早期版本中也能够使用。 - MatteoSp
10
在PowerShell中,Get-Content命令在3.0版本之前默认获取的是一行一行的文本,并且以数组形式存储。但在3.0版本中加入了-Raw参数,可以直接以字符串形式获取全部内容。 - jpmc26
这绝对应该是被接受的答案。并不帮助的是,文档-Raw参数没有被任何本地实现。 - Richard Szalay
谢谢,刚才帮了我很大的忙。 - DAhrens
这并没有完全回答原始问题(需要添加如何计算行号)。但这是一条有用的信息。 - Trisped

149

获取文件的全部内容:

$content = [IO.File]::ReadAllText(".\test.txt")

行数:

([IO.File]::ReadAllLines(".\test.txt")).length
或者
(gc .\test.ps1).length

搞一些技巧性的操作才能包含尾随的空行:

[io.file]::ReadAllText(".\desktop\git-python\test.ps1").split("`n").count

1
谢谢!$content = [IO.File]::ReadAllText(".\test.txt") 看起来与 $content = (gc ".\test.txt" | out-string) 做的事情一样。由于后者更短,所以我更喜欢它。不幸的是,你提供的两种计算总行数的方法都没有考虑到末尾的空白行。还有其他想法吗? - Nick
@Nick 在 .Net(以及 Windows)中,任何带有\r\n的行都会被计算。 - manojlds
我正在进行一些实验,并得出了与您的更新答案相同的结果,但如果没有您的帮助,我不会做到这一点,非常感谢! - Nick
有没有一种透明地将此与 Invoke-WebRequest 结合的方法? - Kareem

32

Powershell 2.0:

(详细解释请见此处)

$text = Get-Content $filePath | Out-String

IO.File.ReadAllText对于相对路径不起作用,它在%USERPROFILE%\$filePath中查找文件,而不是当前目录(至少在从Powershell ISE运行时):

$text = [IO.File]::ReadAllText($filePath)

PowerShell 3+:

$text = Get-Content $filePath -Raw

1
为了使用相对路径,请先解析它,例如:[IO.File]::ReadAllText((Resolve-Path $filePath)) - mvanle

17

我喜欢的另一种文件读取方法被称为变量符号变量语法,它只需要在花括号内用美元符号括起来即可,例如:

$content = ${C:file.txt}

这种符号表示可以作为L值或R值使用;因此,您可以像这样轻松地写入文件:

 ${D:\path\to\file.txt} = $content

另一个方便的用途是,您可以在不使用临时文件和子表达式的情况下直接修改文件,例如:

${C:file.txt} = ${C:file.txt} | select -skip 1

我最初对这个符号感到着迷,因为很难找到有关它的任何信息!即使是PowerShell 2.0规范也只提到了它一次,并仅显示了一行使用它的代码--但没有解释或任何使用细节。后来我在PowerShell变量的博客文章中发现了一些有益的见解。
最后需要注意的一点是:您必须使用驱动器指定,即像我在上面所有示例中所做的那样使用${drive:filespec}。如果没有驱动器(例如${file.txt}),它将无法正常工作。对该驱动器上的文件规范没有限制:它可以是绝对路径或相对路径。

除非在驱动器名称后面加上反斜杠,否则我从未使其工作。 - Charles Anderson
@CharlesAnderson:不清楚您是指其中的哪一个示例,或者也许是全部...无论如何,我刚刚确认在PowerShell V3中,所有3个示例都可以使用相对路径(即没有反斜杠)正常工作。此外,在我回答时,我正在使用V2,因此可能是您的环境中有其他问题导致了此问题。 - Michael Sorens
我的意思是像${C:file.txt}这样的例子,我必须写成${C:\file.txt}。是的,我认为这与我的环境有关,但我不知道具体是什么。 - Charles Anderson
当作为L-value使用时,它使用系统的默认编码。我尝试设置$OutputEncoding但没有效果。当作为R-value使用时,它会生成一个string[]数组。 - robert4
@CameronKerr 是的,似乎是这样。我可能只需编辑此答案以注明。 - Justin Dearing
显示剩余2条评论

3
Get-Content命令可获取数据并逐行将其转储到数组中。假设除了您列出的特殊要求之外没有其他特殊要求,您可以将内容保存到变量中。
$file = Get-Content c:\file\whatever.txt

只需运行$file即可返回完整内容。然后您只需执行$file.Count(因为数组已经内置了计数方法)以获取总行数。

希望这有所帮助!我不是一个脚本专家,但这对我来说似乎比上面的很多东西更容易。


1

读取二进制文件:

虽然这不完全符合要求,但也许有些人会发现这对他们的用例很有用。 Get-Content -Raw 返回一个 string,所以如果你想要 byte[]

Get-Content c:\file.bin -Encoding Byte -ReadCount 0

-Read-Count表示一次处理管道中的多少行(默认为1),而0则会在一次操作中完成所有操作,从而提高性能。

这个解决方案的功劳应归于Shay Levy,他发表了这篇文章:(在这里查看Shay的帖子)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接