Get-Content 真正输出什么,一个字符串或几个属性? [英] What does Get-Content really output, a string or several properties?

查看:48
本文介绍了Get-Content 真正输出什么,一个字符串或几个属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<前>PS C:\Users\me> Get-Content input.txt111PS C:\Users\me> Get-Content input.txt |选择对象 *PSPath : C:\Users\me\input.txtPSParentPath : C:\Users\mePSChildName : 输入驱动器:CPSProvider : Microsoft.PowerShell.Core\FileSystem读取计数:1长度 : 3PS 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

解决方案

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

  • 然而,Get-Content装饰这些字符串对象具有附加属性,这些属性提供了有用的元数据,例如字符串来自.

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

  • 这种装饰是通过 PowerShell 特定的(主要是)不可见的帮助程序类型[psobject] 实现的,其中包装了 .NET 对象,以及可以存储额外的属性.

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

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

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

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

  • 由提供程序 cmdlet(例如 Get-Content)添加的 NoteProperty 成员是 instance 成员,即它们特定于给定的对象.(PowerShell 的 ETS(扩展类型系统) 还允许您在 类型 级别装饰对象).

    • 因此,当您构造一个 new [string] 实例时,例如通过使用 -replace 运算符(或,通常,任何返回字符串的字符串操作),新实例具有附加属性

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


[1] 严格来说,Get-Content,与任何 cmdlet 一样,流式其输出对象,即将它们发送到管道 one一个.只有当你捕获这个输出(例如通过分配给一个变量)是一个按需构造的数组([object[]]),假设输入文件包含两行或更多行 - 否则,唯一的一行被捕获为它自己,而不是包裹在一个数组中 - 请参阅这个答案 了解更多信息.

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

What does Get-Content really output, a string or an object with several properties? If it's an object, which property contains the string, and can I modify that property? The file is only one line so I don't have to deal with an object array.

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

PS C:\Users\me> Get-Content input.txt | Select-Object *

PSPath       : C:\Users\me\input.txt
PSParentPath : C:\Users\me
PSChildName  : input
PSDrive      : C
PSProvider   : Microsoft.PowerShell.Core\FileSystem
ReadCount    : 1
Length       : 3

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

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

-replace erases all of the extra properties except length:

PS C:\Users\me> (Get-Content input.txt) -replace 111, 222 | Select-Object *

Length
------
     3

解决方案

  • Get-Content outputs an array[1] of .NET [string] objects, each representing a line from the input file.

  • However, Get-Content also decorates these string objects with additional properties that provide helpful metadata about where the strings came from.

  • All data-retrieving PowerShell provider cmdlets - Get-ChildItem, Get-Item, Get-Content, ... - do this; specifically they decorate their output objects with the following NoteProperty members: PSPath, PSParentPath, PSChildName, PSDrive, PSProvider.

  • This decorating is made possible by a PowerShell-specific (mostly) invisible helper type, [psobject], in which .NET objects are wrapped, and which can store additional properties.

  • Typically, a decorated .NET object behaves as it normally would; e.g., outputting the strings returned by Get-Content prints them as-is, with no indicating that they now contain additional properties (from PowerShell's perspective).

  • When it comes to serialization, however, or making a [pscustomobject] clone of an object with Select-Object *, or other contexts where reflection (enumeration of properties) is used, these properties do matter and do surface, as shown in your question.

    • When you serialize with ConvertTo-Json, for instance, PowerShell also serializes the additional properties and - somewhat artificially - represents the string's content as pseudo property value - see this answer.

    • Accessing .psobject.BaseObject on a decorated [string] instance - only[2] - allows you to bypass the PowerShell-added properties on demand, returning just the underlying .NET [string] instance (the base object).

  • The NoteProperty members added by provider cmdlets such as Get-Content are instance members, i.e., they are specific to a given object. (PowerShell's ETS (Extended Type System) also allows you to decorate objects at the type level).

    • Therefore, when you construct a new [string] instance, such as by using the -replace operator (or, generally, any string operation that returns a new string), the new instance does not have the additional properties

    • From the perspective of a string operation, even a decorated string is just a string; the added properties are irrelevant in this context. This pattern applies generally: a decorated object can always act as if it were its .NET base object, and in most contexts does.


[1] Strictly speaking, Get-Content, as any cmdlet, streams its output objects, i.e. it emits them to the pipeline one by one. Only when you capture this output (such as by assigning to a variable) is an array ([object[]]) constructed on demand, assuming the input file contains two or more lines - otherwise, the one and only line is captured as itself, not wrapped in an array - see this answer for more information.

[2] In PowerShell version 3 and higher, instance ETS members are no longer associated with a given .NET base object's [psobject] wrapper, but with the base object itself, using so-called resurrection tables. [string] instances are the only exception, for technical reasons, which is why only with [string] instances do you truly get an undecorated object with .psobject.BaseObject - for all other types, accessing the base object is effectively a no-op, as the object returned will still surface instance ETS members (too).
However, .psobject.BaseObject can still be useful for accessing members (properties, methods) of the base object, in case these members are shadowed (overridden) by ETS members of the same name.

这篇关于Get-Content 真正输出什么,一个字符串或几个属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆