70

まず、これが私の質問につながるので、まず、PowerShell で XML をかなり扱ったことがあること、および XML ファイルからカスタム オブジェクトの配列にすばやくデータを読み取る方法について言及することから始めます。たとえば、次の XML ファイルがあるとします。

<stuff>
 <item name="Joe" age="32">
  <info>something about him</info>
 </item>
 <item name="Sue" age="29">
  <info>something about her</info>
 </item>
 <item name="Cat" age="12">
  <info>something else</info>
 </item>
</stuff>

そして、単純に読むと、次のようになります。

[xml]$myxml = Get-Content .\my.xml

次に、次のようにアイテムの配列を取得できます。

[array]$myitems = $myxml.stuff.Item
$myitems

name   age  info
----   ---  ----
Joe    32   something about him
Sue    29   something about her
Cat    12   something else

だから、今私の質問:

カスタム オブジェクトの配列の同様の構造を作成し、ファイルを読み取らにスクリプトで初期化するにはどうすればよいですか?

個々のオブジェクトを多数のループおよび/または多数の作成/初期化してから、一度に 1 つずつ配列に追加できます...

しかし、この作成/初期化をより簡単な方法で実行する方法があるはずです。ここで重要なのは、カスタム オブジェクトに 3 つ以上の要素があることです (そうでなければ、ハッシュを使用していたはずです)。

XML の大きな文字列を作成し、Select-XML を使用することも検討しましたが、正しい構文を取得できませんでした (それが適切な方法であったとしても)。

4

9 に答える 9

104

私はこれらの行に沿って何かをします:

$myitems =
@([pscustomobject]@{name="Joe";age=32;info="something about him"},
[pscustomobject]@{name="Sue";age=29;info="something about her"},
[pscustomobject]@{name="Cat";age=12;info="something else"})

これはPowerShell 3でのみ機能することに注意してください。ただし、質問でバージョンについて言及していないため、これは問題ではないと想定しています。

アップデート

コメントでは、次のことを行うと言及されています。

$younger = $myitems | Where-Object { $_.age -lt 20 } 
Write-Host "people younger than 20: $($younger.Length)" 

期待どおりにはなりません1。これは、シングルpscustomobjectが返されたときに発生します。PowerShell の他のほとんどのオブジェクトには と の代理プロパティがあるため、これは問題になりませLengthCount。残念ながらpscustomobjectそうではありません。これは、PowerShell 6.1.0 で修正されています。operator を使用してこれを回避できます@()

$younger = @($myitems | Where-Object { $_.age -lt 20 })

背景の詳細​​については、こちらこちらを参照してください。

更新 2

PowerShell 5 では、クラスを使用して同様の機能を実現できます。たとえば、次のようなクラスを定義できます。

class Person {
    [string]$name
    [int]$age
    [string]$info; `
`
    Person(
    [string]$name,
    [int]$age,
    [string]$info
    ){
        $this.name = $name
        $this.age = $age
        $this.info = $info
    }
}

ここでのバッククォートは、コマンド ラインにコピー アンド ペーストできるようにするためのものであり、スクリプトでは必要ありません。クラスが定義されたら、通常の方法で配列を作成できます。

$myitems =@([Person]::new("Joe",32,"something about him"),
[Person]::new("Sue",29,"something about her"),
[Person]::new("Cat",12,"something else"))

この方法には、PowerShell 5 でも、前回の更新で述べた欠点がないことに注意してください。

アップデート 3

最初の例と同様に、ハッシュテーブルを使用してクラス オブジェクトを初期化することもできます。そのためには、デフォルトのコンストラクターが定義されていることを確認する必要があります。コンストラクターを提供しない場合は作成されますが、デフォルト以外のコンストラクターを提供する場合、デフォルトのコンストラクターは存在しないため、明示的に定義する必要があります。自動作成されるデフォルトのコンストラクターの例を次に示します。

class Person {
    [string]$name
    [int]$age
    [string]$info;
}

これにより、次のことができます。

$person = @([Person]@{name='Kevin';age=36;info="something about him"}
[Person]@{name='Sue';age=29;info="something about her"}
[Person]@{name='Cat';age=12;info="something else"})

これはもう少し冗長ですが、もう少し明示的でもあります。これを指摘してくれた@js2010に感謝します。

于 2013-06-27T23:17:52.000 に答える
38

PowerShell でハッシュテーブルの配列を初期化する簡潔な方法を次に示します。

> $body = @( @{ Prop1="1"; Prop2="2"; Prop3="3" }, @{ Prop1="1"; Prop2="2"; Prop3="3" } )
> $body

Name                           Value
----                           -----
Prop2                          2
Prop1                          1
Prop3                          3
Prop2                          2
Prop1                          1
Prop3                          3  
于 2014-10-16T22:26:59.460 に答える
28

たぶん、あなたはこのように意味しますか?オブジェクトを作成して Format-Table を使用するのが好きです。

> $array = @()
> $object = New-Object -TypeName PSObject
> $object | Add-Member -Name 'Name' -MemberType Noteproperty -Value 'Joe'
> $object | Add-Member -Name 'Age' -MemberType Noteproperty -Value 32
> $object | Add-Member -Name 'Info' -MemberType Noteproperty -Value 'something about him'
> $array += $object
> $array | Format-Table

Name                                                                        Age Info
----                                                                        --- ----
Joe                                                                          32  something about him

これにより、配列内にあるすべてのオブジェクトが、そのプロパティに従って列に配置されます。

ヒント:-autoテーブルのサイズをより適切に使用する

> $array | Format-Table -Auto

Name Age Info
---- --- ----
Joe   32 something about him

テーブルに必要なプロパティを指定することもできます。各プロパティ名をコンマで区切るだけです:

> $array | Format-Table Name, Age -Auto

Name Age
---- ---
Joe   32
于 2013-06-27T22:16:11.767 に答える