【问题标题】:PowerShell Get-Content -ReadCountPowerShell 获取内容 -ReadCount
【发布时间】:2021-08-14 21:22:46
【问题描述】:

我想知道以下两个几乎相同的陈述之间的区别:

Get-Content c:\temp\myfile.txt -ReadCount 10 | ForEach-Object { $_ -match 'my_string' }
Get-Content c:\temp\myfile.txt | ForEach-Object { $_ -match 'my_string' }

第一个语句返回 myfile.txt 中存在匹配子字符串的行,而第二个语句根据传递给 ForEach 的每一行的匹配返回 true 或 false。

为什么这种行为不直观(尤其是第一个)?如果不运行代码,我会为这两个语句的输出选择真/假。

谢谢。

【问题讨论】:

  • 在第一种情况下,您不会一次将一行传递给管道。相反,一次有十行。这就是-match 运算符切换到其过滤模式并输出过滤后的行的原因。
  • 您可以阅读更多关于帮助主题about_Comparison_Operators
  • 谢谢奥拉夫。我认为 Get-Content 中的 -readcount 仅与文件 I/O 操作有关(一次读取 10 行,而不是一次从文件中读取一行,否则会导致 I/O 缓慢)。我不知道所有 10 行都作为单个数组/集合传递到 foreach - 我在想即使一次读取 10 行,它们中的每一行都一次传递给 foreach 。这是否意味着在内部 Get-Content 使用逗号运算符将 10 行作为数组传递到 foreach 中,语法为 ,$TempArrayOfTenLines ? (注意,$ 符号前有一个逗号。
  • @Steve 这是一个有效的问题,您可以自己看到 X 行通过执行 { $_.Count } 传递通过管道,这也解释了为什么在 ReadCount 示例 -matches 的行为就像它正在做的那样。

标签: powershell


【解决方案1】:

Olaf 在评论中提供了关键指针;让我充实一下:

  • Get-Content-ReadCount 参数通过管道发送从输入文件读取的数组(批次)行。

  • 因此,接收ForEach-Object 调用中的automatic $_ variable 然后引用行的数组 而不是单行 行,就像没有-ReadCount

  • 以一个数组(集合)作为LHS,PowerShell的比较运算符如-matchact as filters并返回匹配项的子数组而不是布尔值。

    • -match 的情况下,特别是使用数组值 LHS 还意味着 automatic $Matches variable,它报告 -match 操作捕获的文本是 填充

换一种说法:

虽然使用Get-Content -ReadCount 结合ForEach-Object 可以加快文本文件的处理速度,但您需要迭代$_ 中报告的数组元素 逐行处理:

Get-Content c:\temp\myfile.txt -ReadCount 10 | 
  ForEach-Object { foreach ($line in $_) { $line -match 'my_string' } }

请注意,common -OutBuffer parameter 的行为与您预期的一样:-OutBuffer $n 表示手头的 cmdlet 在输出到管道之前收集 1 + $n 对象,但是,此时它们是输出 一个接一个,像往常一样。

也就是说,除非$n 的值很大,否则很少使用的-OutBuffer 参数提供没有性能优势,甚至可能会减慢速度。

【讨论】:

  • 这是否意味着 -Readcount 在这里执行 2 个不同的功能 - 1. 从文件中一次读取 'n' 行(为了更快的 I/O 和 2. 将这些 'n' 行作为数组传递进入 foreach 而不是在将项目单独移动到 foreach 之前先遍历该数组?
  • @Steve,是的,一个 10 行的 array 被传递给每个 ForEach-Object 调用,因此 $_ 然后引用整个数组。你是这个意思吗?
  • 如果在 Foreach 中使用 Where-Object,这种流式传输行为将如何变化?例如获取内容 c:\temp\myfile.txt -ReadCount 10 | Where-Object { $_ -match 'my_string' } 我得到的输出并不那么令人信服。顺便说一下,我的输入文件是 22 GB。
  • @Steve,它不会改变:行为内置于Get-Content,因此哪个 cmdlet 接收其输出并不重要。除非您真的可以使用 -ReadCount 批量处理行 - 无需单独查看行 - 最好避免使用 Get-Content 处理大文件,而使用 switch-File 代替,可能与 System.IO.StreamWriter 结合使用例如写入文件。请参阅this answer 了解更多信息。
  • 我确实在同一个 22 GB 文件上尝试了 Switch -file 选项。在性能方面,它并没有太大的不同。 Get-Content 看起来比不那么明显的 Switch -File 语法更具可读性,因此现在我坚持使用 Get-Content 方法。
猜你喜欢
  • 1970-01-01
  • 2021-10-26
  • 2021-03-13
  • 1970-01-01
  • 1970-01-01
  • 2020-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多