如何让 Measure-Object 正确计算最后一行没有 CRLF 的文件的行数?

How to have Measure-Object count number of lines correctly for files not having CRLF at the last line?

提问人:Ooker 提问时间:8/26/2023 更新时间:8/26/2023 访问量:75

问:

在我的理解中,应该返回文件中的总行数。它适用于某些文件,但对于某些生成的文件,它给出的结果比正确的数字小 1。我检查了它们,发现在最后一行他们没有 CRLF。(Get-Content $file | Measure-Object).count

为什么会这样?以及如何确保我得到正确的结果?Measure-Object 文档似乎没有解释这一点。

PowerShell 计数 换行 测量对象

评论


答:

2赞 mklement0 8/26/2023 #1

该行为与 Measure-Object 无关:

Get-Content 逐一读取和流式传输给定文件的行,如果最后一行存在,则去除其尾随换行符

也就是说,对于 Get-Content 来说,最后一行是否有尾随换行符(即文件是否以换行符结尾)没有区别

如果你想计算文件中换行符(LF或CRLF序列)的实际数量,你需要一种不同的方法(如果你想将最终的换行符本身视为一行,则可能需要添加),例如:1

# Count the number of newlines
[regex]::Matches((Get-Content -Raw $file), '\n').Count

或者:

((Get-Content -Raw $file) -replace '[^\n]').Length

请注意 with 的用法,它将文件作为一个整体读入单个(通常)多行字符串,从而保留所有换行符。-RawGet-Content

评论

1赞 Ooker 8/26/2023
我认为让我在这里感到困惑的是此 cmdlet 如何定义行与 Notepad++ 等编辑器如何向我显示“行”之间的区别。我认为计算由 CRLF 分隔的非 CRLF 字符串的数量,而每当出现 CRLF 时,编辑器都会将光标向下移动一行。因此,对于末尾有 CRLF 的文本,编辑器中显示的行数将比用 CRLF 分隔的非 CRLF 字符串数大 1。我认为对线有更好的定义Get-ContentGet-Content
1赞 mclayton 8/27/2023
@Ooker - 我想这取决于你是否将空字符串视为一行文本 - 如果文件完全由一个空字符串组成,那么 will 之前的空字符串大概算作一行,那么为什么不后面的空字符串呢扩展而言,0 字节文件是 0 行还是 1 行?(反问句,顺便说一句 - 我不认为任何一种方式在客观上都是“正确的” - 只是取决于你当时在做什么:-))CRLFCRLF
1赞 mklement0 8/29/2023
@mclayton,好点。对于 POSIX 来说,换行符是强制性的行终止符。文件末尾的任何非换行符的非空运行都是不完整的行。因此,没有歧义:换行符数等于行数,并且仅报告换行符的计数,这意味着不完整的行不计算在内。因此,一个 -byte 文件以及一个仅包含不完整行的文件的行数为 。wc -l00
1赞 mklement0 8/29/2023
相比之下,对于 PowerShell,换行符是可选的行终止符,这意味着最后一行可以(但不必)以换行符终止。事实上,因为没有通过管道发送任何 -byte 文件,因此在这种情况下报告行计数,但确实会计算 POSIX 意义上的不完整行,因为报告不完整的行就像报告完整的行一样。请参阅 GitHub 问题 #3911 讨论如何处理 -byte 文件。Get-Content0Measure-Object0Get-ContentGet-Content -Raw0