首页 > 解决方案 > `cat 一些文件 | powershell 中的 cat` 给出 10000 行而不是 100

问题描述

有人可以在这里解释我的误解吗? cat somefile | cat正在输出10000行而不是100 行。我已经习惯了管道的 Unix 行为。这是重现问题的脚本(需要在 PowerShell 提示符下逐行输入):

seq 1 100 > somefile
cat somefile  # works as expected, outputs 100 lines
cat somefile | Measure-Object  # 100 lines, expected.
cat somefile | cat  # OUTPUTS 10000 lines!!!
# wait did I really just see that
cat somefile | cat | Measure-Object
# 10000 lines??!!!
cat somefile | cat | cat | Measure-Object
# 57300 lines???  That's not even a pattern!

很明显,我不知道这里发生了什么。我期望 bash 行为。我知道这样做没有用cat somefile | cat,但这仍然令人惊讶。

Bash 行为cat somefile | cat | cat | cat总是给出与 just 完全相同的内容cat somefile

标签: powershell

解决方案


为方便起见,我假设引入了别名(catGet-ContentUnix 用户对 PowerShell 感觉更舒服)。不过,这并不Get-Content像 Unix command 一样cat。该 cmdlet 特别不回显来自管道的字符串输入:

PS C:\Temp> 'foo' | cat 
cat :输入对象也不能绑定到命令的任何参数
因为该命令不接受管道输入或输入及其属性
不匹配任何接受管道输入的参数。
在行:1 字符:9
+ '富' | 猫
+ ~~~

这就是Write-Output(或其别名echo)的用途:

PS C:\Temp> 'foo' | 写输出

Get-Content接受管道输入的默认参数分别是-Path-LiteralPath,两者都期望有效路径。

在仔细检查您的输出后,Get-Content您会注意到这些对象不仅具有字符串对象的通常属性,而且还具有一些属性,其中包含有关从中读取数据的文件的信息,特别是PSPath

PS C:\Temp> 4..6 > out.txt 
PS C:\Temp> cat .\out.txt
4
5
6
PS C:\Temp> cat .\out.txt | 获取会员

   类型名称:System.String

名称 MemberType 定义
---- ---------- ----------
...
PSChildName NoteProperty string PSChildName=out.txt
PSDrive NoteProperty PSDriveInfo PSDrive=C
PSParentPath 注意属性字符串 PSParentPath=C:\Temp
PSPath NoteProperty string PSPath=C:\Temp\out.txt 
PSProvider NoteProperty ProviderInfo PSProvider=Microsoft.PowerShell.Core\FileSystem
ReadCount NoteProperty long ReadCount=1
Chars ParameterizedProperty char Chars(int index) {get;}
长度属性 int 长度 {get;}

PSPath属性用作第二个的输入Get-Content,导致输入文件中的每一行触发Get-Content同一文件的另一行。但是,第一个输出对象Get-Content也有一个属性ReadCount(指示已经从文件中读取的行数),它也恰好是Get-Content. 因此,第二个Get-Content读取输入文件方式与第一个不同。ReadCount=2一次读取文件中的 2 行,一次读取ReadCount=33 行,依此类推。

PS C:\Temp> cat .\out.txt | cat 
4    # ← 输入第 1 行(“4”),ReadCount = 1,第一次读取(返回“4”) 
5    # ← 输入第 1 行(“4”),ReadCount = 1,第二次读取(返回“5”) 
6    # ← 输入第 1 行(“4”),ReadCount = 1,第三次读取(返回“6”) 
4    # ← 输入第 2 行(“5”),ReadCount = 2,第一次读取(返回“4”,“5” )
5
6    # ← 输入第 2 行(“5”),ReadCount = 2,第二次读取(返回“6”) 
4    # ← 输入第 3 行(“6”),ReadCount = 3,第一次读取(返回“4”,“5” ", "6")
5
6

因此,额外的管道步骤 ( cat .\out.txt | cat | cat ...) 不会产生 n m输出行(n即文件中的行m数和管道步骤的数量)。


推荐阅读