Get-Content 真正输出什么,一个字符串或几个属性?

js2*_*010 4 string powershell

什么Get-Content真正输出,一个字符串或一个具有多个属性的对象?如果它是一个对象,哪个属性包含字符串,我可以修改该属性吗?该文件只有一行,所以我不必处理对象数组。

PS C:\Users\me> Get-Content input.txt
111

PS C:\Users\me> Get-Content input.txt | 选择对象 *

PSPath : C:\Users\me\input.txt
PSParentPath : C:\Users\me
PSChildName : 输入
驱动器:C
PSProvider : Microsoft.PowerShell.Core\FileSystem
读取计数:1
长度 : 3

PS C:\Users\me> (Get-Content input.txt).GetType()

IsPublic IsSerial 名称 BaseType
——————————————————
真真字符串 System.Object

-replace 擦除除长度以外的所有额外属性:

PS C:\Users\me> (Get-Content input.txt) -replace 111, 222 | 选择对象 *

长度
------
     3

mkl*_*nt0 9

  • Get-Content输出.NET对象的数组[1][string],每个对象代表输入文件中的一行。

  • 但是,Get-Content还使用附加属性装饰这些字符串对象,这些属性提供有关字符串来源的有用元数据。

  • 所有数据检索PowerShell 提供程序cmdlet - Get-ChildItem, Get-Item, Get-Content, ... - 执行此操作;具体来说,他们用以下NoteProperty成员装饰他们的输出对象:PSPath, PSParentPath, PSChildName, PSDrive, PSProvider

  • 这种装饰由PowerShell的特定(大部分)成为可能不可见的辅助类型[psobject],其中.NET对象被包裹,并且其可以存储附加的属性。

  • 通常,经过修饰的 .NET 对象的行为与正常情况一样;例如,输出由 返回的字符串按Get-Content原样打印它们,没有指示它们现在包含其他属性(从 PowerShell 的角度来看)。

  • 但是,当涉及到序列化时,或者[pscustomobject]使用Select-Object *或其他使用反射 (属性枚举)的上下文制作对象的克隆时,这些属性确实很重要,并且会浮出水面,如您的问题所示。

    • ConvertTo-Json例如,当您使用 进行序列化时,PowerShell 还会序列化其他属性,并且 - 有点人为地 - 将字符串的内容表示为伪属性value- 请参阅此答案

    • 访问.psobject.BaseObject装饰[string]实例 - 仅[2] - 允许您根据需要绕过PowerShell 添加的属性,仅返回底层 .NET[string]实例(基础对象)。

  • NoteProperty由提供者小命令如添加的成员Get-Content实例成员,即,它们是专用于一个给定的对象。(PowerShell 的ETS(扩展类型系统)还允许您在类型级别装饰对象)。

    • 因此,当构造一个新的 [string]实例,如通过使用-replace操作者(或者,一般地,返回的任何字符串操作的字符串),则新实例并具有额外的特性

    • 从字符串操作的角度来看,即使是修饰过的字符串也只是字符串;添加的属性在此上下文中无关紧要。这种模式通常适用:装饰对象总是可以像它的 .NET 基对象一样运行,并且在大多数情况下也是如此。


[1] 严格来说,Get-Content就像任何 cmdlet 一样,流式传输其输出对象,即将它们一个一个地发送到管道。只有当您捕获此输出(例如通过分配给变量)时,才会根据需要构造一个数组( [object[]]),假设输入文件包含两行或更多行- 否则,唯一一行被捕获为自身,而不是包裹在数组 -有关更多信息,请参阅此答案

[2] 在 PowerShell 版本 3 及更高版本中,实例 ETS 成员不再与给定的 .NET 基础对象的[psobject]包装器相关联,而是与基础对象本身相关联,使用所谓的复活表。[string]出于技术原因,实例是唯一的例外,这就是为什么只有使用[string]实例才能真正获得未修饰的对象.psobject.BaseObject- 对于所有其他类型,访问基础对象实际上是无操作的,因为返回的对象仍将显示实例 ETS成员(也是)。
但是,.psobject.BaseObject对于访问基础对象的成员(属性、方法)仍然很有用,以防这些成员被同名的 ETS 成员遮蔽(覆盖)。


The*_*heo 5

Get-Content不带开关的 cmdlet返回-Raw一个字符串数组,其中包含文本文件的所有行,并按换行符分割。Get-Content与开关一起使用-Raw,将文件的内容作为单个字符串返回,包括换行符。

话虽如此,如果(如您的情况)文本文件仅包含一行,PowerShell 会自动“拆箱”返回的数组并返回单个字符串。

.NET 中的字符串是对象,具有属性和方法。尝试"abc" | Get-Member看看还有什么关于 String 对象的信息。

如果这样做"abc" | Select-Object *,输出将是

Length
------
     3
Run Code Online (Sandbox Code Playgroud)

PowerShell 现在仅显示Length字符串的属性。

Get-Content然而,正如Ansgar Wiechers已经评论的那样,向结果(字符串)对象添加了额外的信息,所有这些都与文件本身有关。( PSPath, PSParentPath, PSChildName, PSDrive, PSProvider, ReadCount)。这些额外的属性都被添加为NoteProperty,如果您这样做,您可以看到它们被添加

(Get-Content input.txt) | Get-Member
Run Code Online (Sandbox Code Playgroud)

这会返回一个令人印象深刻的列表,但该对象仍然是System.String类型。

当您使用-replace对该字符串执行操作时(Get-Content input.txt) -replace 111, 222,结果将是New String 对象,该对象不再具有额外的与文件相关的属性。现在它只是一个字符串,因此与它最初的来源无关。

希望能解释一下