配列について知りたいことはすべて、ほとんどのプログラミング言語の基本的な言語機能です。 それらは値またはオブジェクトの集合であり、したがって回避することは困難です。 配列とそれらが提供しなければならないすべてを詳しく見てみましょう。
- ページインデックス
- 配列とは何ですか?,マッチ
- All-eq
- 配列の追加
- プラスは+=
- パイプライン割り当て
- 厳密に型付けされた配列
- ArrayList
- 汎用リスト
- リスト
- remove()
- より多くのコレクション
- 事前サイズの配列
- 配列を乗算
- 0で初期化
- ネストされた配列
- Write-output-noenumerate
- 配列を返す
配列とは何ですか?
私は、PowerShellがそれらを利用する他の方法に移行する前に、配列が何であるか、そしてそれらがほとんどのプログラミング言語でどのように使われているかについての基本的な技術的説明から始めます。
配列は、複数のアイテムのコレクションとして機能するデータ構造です。 配列を反復処理するか、インデックスを使用して個々の項目にアクセスできます。 配列は、各値が他の値のすぐ隣に格納されているメモリの連続したチャンクとして作成されます。
私たちが行くように私はそれらの詳細のそれぞれに触れます。,
基本的な使い方
配列はPowerShellの基本的な機能なので、PowerShellでそれらを操作するための簡単な構文があります。
@()で配列を作成します
空の配列は、@()
PS> $data = @() PS> $data.count 0
配列を作成し、@()
かっこに配置するだけで値でシードすることができます。
PS> $data = @('Zero','One','Two','Three') PS> $data.count 4 PS> $data Zero One Two Three
この配列には4つの項目があります。 $data
変数を呼び出すと、アイテムのリストが表示されます。, それが文字列の配列であれば、文字列ごとに一行があります。
複数の行で配列を宣言できます。 この場合、コンマは省略可能で、通常は省略されます。
$data = @( 'Zero' 'One' 'Two' 'Three' )
私はそのような複数行で配列を宣言することを好みます。 複数のアイテムがあるときに読みやすくなるだけでなく、ソース管理を使用するときに以前のバージョンと比較しやすくなります。,
その他の構文
一般的に理解されています@()
配列を作成するための構文ですが、コンマ区切りのリストはほとんどの場合
$data = 'Zero','One','Two','Three'
配列を作成するための書き込み出力
言及する価値のあるクールな小さなトリックは、Write-Output
コンソールで文字列をすばやく作成できることです。
$data = Write-Output Zero One Two Three
パラメータが文字列を受け入れるときに文字列を引用符で囲む必要がないので、これは便利です。, こいこのスクリプトで公正なゲームのソフトである。
アイテムにアクセスする
アイテムが含まれる配列ができたので、それらのアイテムにアクセスして更新することができます。
Offset
個々のアイテムにアクセスするには、0から始まるオフセット値を持つ角かっこを使用します。 これは、配列の最初の項目を取得する方法です。
PS> $data = 'Zero','One','Two','Three' PS> $data Zero
ここでゼロを使用する理由は、最初の項目がリストの先頭にあるため、0項目のオフセットを使用してそれに到達するためです。, 第二の項目に到達するには、最初の項目をスキップするために1のオフセットを使用する必要があります。
PS> $data One
これは、最後の項目がオフセット3にあることを意味します。
PS> $data Three
Index
これで、この例で行った値を選択した理由がわかります。 私はこれをオフセットとして導入しましたが、このオフセットはより一般的にインデックスと呼ばれています。 0
で始まるインデックス。 この記事の残りの部分では、オフセットをインデックスと呼びます。,
特殊なインデックストリック
ほとんどの言語では、インデックスとして単一の番号しか指定できず、単一のアイテムを取得します。 PowerShellははるかに柔軟性があります。 複数のインデックスを一度に使用できます。 索引のリストを提供することにより、いくつかの項目を選択できます。
PS> $data Zero Two Three
アイテムは、指定されたインデックスの順序に基づいて返されます。 インデックスを複製すると、そのアイテムが両方の時間取得されます。,
PS> $data Three Zero Three
組み込みの..
演算子で数値のシーケンスを指定できます。
PS> $data One Two Three
これは逆にも機能します。
PS> $data Three Two One
あなたは最後からオフセットするために否定的なインデックス値を使用することができます。 したがって、リストの最後の項目が必要な場合は、-1
を使用できます。,
PS> $data Three
out of bounds
ほとんどの言語では、配列の終わりを過ぎた項目のインデックスにアクセスしようとすると、何らかのタイプのエラーまたは例外が発生します。 PowerShellは静かにあなたに何も与えません。
PS> $null -eq $data True
null配列にインデックスを付けることはできません
変数が$null
配列のようにインデックスを付けようとすると、System.Management.Automation.RuntimeException
メッセージCannot index into a null array
.,
PS> $empty = $null SP> $empty Error: Cannot index into a null array.
したがって、配列が$null
それらの中の要素にアクセスしようとする前に、配列が$null
でないことを確認してください。
Count
配列やその他のコレクションには、配列内にあるアイテムの数を示すcountプロパティがあります。
PS> $data.count 4
PowerShell3.0では、ほとんどのオブジェクトにcountプロパティが追加されました。 単一のオブジェクトを持つことができ、1
カウントを与える必要があります。,
PS> $date = Get-Date PS> $date.count 1
Even$null
は、0
を返す以外はcountプロパティを持ちます。
PS> $null.count 0
ここでは、$null
またはこの記事の後半で空の配列のチェックを取り上げるときに再訪するトラップがいくつかあります。
Off by one errors
配列はインデックス0から始まるため、一般的なプログラミングエラーが作成されます。 オるエラーで教えることができるも共通です。,
最初は精神的にあなたが2番目の項目が欲しいと思い、2
のインデックスを使用して、本当に第三の項目を取得することです。 または、4
アイテムがあり、最後のアイテムが必要なので、サイズを使用して最後のアイテムにアクセスするだけです。
$data
PowerShellは、それを実行して、インデックス4、$null
に存在するアイテムを正確に提供できることを完全に嬉しく思っています。 あなたが使用する必要があります$data.count - 1
または-1
上記について学びました。,
PS> $data Three
これは、-1
インデックスを使用して最後の要素を取得できる場所です。
PS> $data Three
Lee Daileyはまた、$data.GetUpperBound(0)
最大インデックス番号を取得することができることを私に指摘しました。
PS> $data.GetUpperBound(0) Three
第二の最も一般的な方法は、リストを反復処理し、適切なタイミングで停止しないときです。 私たちはfor
ループを使用して話すとき、私はこれを再訪します。,
アイテムの更新
同じインデックスを使用して、配列内の既存のアイテムを更新できます。 これは私達に個々の項目を更新する直接アクセスを与える。
$data = 'dos' $data = 'tres'
最後の要素を過ぎたアイテムを更新しようとすると、Index was outside the bounds of the array.
エラーが発生します。
後で配列を大きくする方法について話すときに、これを再訪します。
反復
ある時点で、リスト全体をウォークまたは反復処理し、配列内の各項目に対して何らかのアクションを実行する必要があります。,
パイプライン
配列とPowerShellパイプラインはお互いのためのものです。 これは、これらの値を処理する最も簡単な方法の一つです。 配列をパイプラインに渡すと、配列内の各項目が個別に処理されます。
PS> $data = 'Zero','One','Two','Three' PS> $data | ForEach-Object {"Item: "} Item: Item: Item: Item:
$PSItem
前に見たことがない場合は、$_
と同じことを知っています。 どちらかをお使いいただけますがそのことを表す現在のオブジェクトのパイプライン,
ForEachループ
ForEach
ループはコレクションでうまく機能します。 構文を使用して:foreach ( <variable> in <collection> )
foreach ( $node in $data ) { "Item: " }
ForEachメソッド
私はこれを忘れる傾向がありますが、単純な操作ではうまくいきます。 PowerShellでは、コレクションで.ForEach()
を呼び出すことができます。
PS> $data.foreach({"Item "}) Item Item Item Item
.foreach()
スクリプトブロックであるパラメータを取ります。 括弧を削除して、スクリプトブロックを提供するだけです。,
$data.foreach{"Item "}
これはあまり知られていない構文ですが、同じように動作します。 このforeach
メソッドはPowerShell4.0で追加されました。
for loop
for
ループは他のほとんどの言語で頻繁に使用されていますが、PowerShellではあまり見られません。 あなたがそれを見るとき、それはしばしば配列を歩くという文脈にあります。
for ( $index = 0; $index -lt $data.count; $index++) { "Item: " -f $data }
最初に行うことは、$index
を0
に初期化することです。, 次に、$index
が$data.count
より小さくなければならないという条件を追加します。 最後に、ループするたびに1
でインデックスを増やす必要があることを指定します。 この場合、$index++
は$index = $index + 1
の略です。
for
ループを使用しているときはいつでも、条件に特に注意してください。 ここで$index -lt $data.count
を使用しました。 あなたのロジックで一つのエラーでオフにするには、条件を少し間違って取得することは非常に簡単です。, 使用$index -le $data.count
または$index -lt ($data.count - 1)
少し間違っています。 それはあなたの結果が多すぎるか少なすぎる項目を処理する原因になります。 これは一つのエラーによって古典的なオフです。
スイッチループ
これは非常に見落としやすいものです。 Switchステートメントに配列を指定すると、配列内の各項目に一致します。
$data = 'Zero','One','Two','Three' switch( $data ) { 'One' { 'Tock' } 'Three' { 'Tock' } Default { 'Tick' } }
これにより、次の出力が生成されます。
Tick Tock Tick Tock
switchステートメントでできるこのようなクールなことがたくさんあります。, 私はこれに専念する別の記事を持っています。
- switchステートメントについて知りたかったことすべて
値の更新
配列が文字列または整数(値型)のコレクションである場合、配列内の値をループ 上記のループのほとんどは、値のコピーを保持するループ内の変数を使用します。 その変数を更新すると、配列内の元の値は更新されません。このステートメントの例外は、for
ループです。, 配列を歩いてその中の値を更新したい場合は、for
ループが探しているものです。
for ( $index = 0; $index -lt $data.count; $index++ ) { $data = "Item: " -f $data }
この例では、インデックスごとに値を取得し、いくつかの変更を行い、その同じインデックスを使用して割り当てます。
オブジェクトの配列
これまでのところ、配列に配置した唯一のものは値型ですが、配列にはオブジェクトを含めることもできます。
$data = @( @{FirstName='Kevin';LastName='Marquette'} @{FirstName='John'; LastName='Doe'} )
多くのコマンドレットは、変数に割り当てるときにオブジェクトのコレクションを配列として返します。,
$processList = Get-Process
すでに説明した基本機能はすべて、指摘する価値のあるいくつかの詳細を持つオブジェクトの配列に適用されます。
プロパティへのアクセス
値型と同じように、インデックスを使用してコレクション内の個々の項目にアクセスできます。
PS> $data FirstName LastName ----- ---- Kevin Marquette
プロパティに直接アクセスして更新することができます。,
PS> $data.FirstName Kevin PS> $data.FirstName = 'Jay' PS> $data FirstName LastName ----- ---- Jay Marquette
配列プロパティ
通常、すべてのプロパティにアクセスするには、次のようにリスト全体を列挙する必要があります。
PS> $data | ForEach-Object {$_.LastName} Marquette Doe
またはSelect-Object -ExpandProperty
コマンドレット。
PS> $data | Select-Object -ExpandProperty LastName Marquette Doe
しかし、PowerShellはLastName
直接リクエストする機能を提供します。 PowerShellはそれらをすべて列挙し、きれいなリストを提供します。,
PS> $data.LastName Marquette Doe
列挙はまだ発生しますが、その背後にある複雑さはわかりません。
Where-Object filtering
これは、Where-Object
が入る場所ですので、オブジェクトのプロパティに基づいて配列から必要なものをフィルタリング
PS> $data | Where-Object {$_.FirstName -eq 'Kevin'} FirstName LastName ----- ---- Kevin Marquette
私たちが探しているFirstName
を取得するために、このような同じクエリを書くことができます。,
$data | Where FirstName -eq Kevin
Where()
配列にはWhere()
メソッドがあり、フィルターにscriptblock
を指定できます。
$data.Where({$_.FirstName -eq 'Kevin'})
この機能はPowerShell4.0で追加されました。
ループ内のオブジェクトの更新
値型では、配列を更新する唯一の方法は、値を置き換えるインデックスを知る必要があるため、forループを使用す てのオプションオブジェクトが参照す。, 簡単な例は次のとおりです。
foreach($person in $data) { $person.FirstName = 'Kevin' }
このループは、$data
配列のすべてのオブジェクトを歩いています。 オブジェクトは参照型であるため、$person
変数は配列内にあるオブジェクトとまったく同じオブジェクトを参照します。 で更新などの特性を最新のオリジナルです。
この方法ではオブジェクト全体を置き換えることはできません。 新しいオブジェクトを$person
変数に割り当てようとすると、変数参照を配列内の元のオブジェクトを指さなくなった別のものに, これはあなたが期待するように動作しません:
foreach($person in $data) { $person = @{ FirstName='Kevin' LastName='Marquette' } }
演算子
PowerShellの演算子は配列でも動作します。 その作品は若干異なる。
-join
-join
演算子が最も明白なものなので、最初に見ていきます。 私は-join
演算子が好きで、頻繁に使用します。 配列内のすべての要素を、指定した文字または文字列で結合します。,
PS> $data = @(1,2,3,4) PS> $data -join '-' 1-2-3-4 PS> $data -join ',' 1,2,3,4
私が好きな機能の一つ-join
演算子は、単一のアイテムを処理することです。
PS> 1 -join '-' 1
私はこれをロギングと冗長なメッセージの中で使用します。
PS> $data = @(1,2,3,4) PS> "Data is $($data -join ',')." Data is 1,2,3,4.
-join$array
これはLee Daileyが私に指摘した巧妙なトリックです。, 区切り文字なしですべてを結合したい場合は、これを行う代わりに:
PS> $data = @(1,2,3,4) PS> $data -join $null 1234
-join
配列を接頭辞なしのパラメータとして使用できます。 この例を見て、私が話していることを確認してください。
PS> $data = @(1,2,3,4) PS> -join $data 1234
-replace and-split
-replace
および-split
のような他の演算子は、配列内の各項目で実行されます。 私はこのようにそれらを使用したことがあるとは言えませんが、ここに例があります。,
PS> $data = @('ATX-SQL-01','ATX-SQL-02','ATX-SQL-03') PS> $data -replace 'ATX','LAX' LAX-SQL-01 LAX-SQL-02 LAX-SQL-03
-contains
-contains
演算子を使用すると、値の配列をチェックして、指定された値が含まれているかどうかを確認できます。
PS> $data = @('red','green','blue') PS> $data -contains 'green' True
-in
複数の値のいずれかと一致することを確認する単一の値がある場合は、-in
演算子を使用できます。 値は操作の左側にあり、配列は右側にあります。,
PS> $data = @('red','green','blue') PS> 'green' -in $data True
リストが大きい場合、これは高価になる可能性があります。 4-5以上の値をチェックしている場合は、正規表現パターンをよく使用します。
PS> $data = @('red','green','blue') PS> $pattern = "^({0})$" -f ($data -join '|') PS> $pattern ^(red|green|blue)$ PS> 'green' -match $pattern True
-eqと-ne
等価性と配列は複雑になる可能性があります。 配列が左側にある場合、すべての項目が比較されます。 True
を返す代わりに、一致するオブジェクトを返します。,
PS> $data = @('red','green','blue') PS> $data -eq 'green' green
-ne
演算子を使用すると、値と等しくないすべての値が取得されます。
PS> $data = @('red','green','blue') PS> $data -ne 'green' red blue
これをif()
ステートメントで使用すると、返される値はTrue
値になります。 値が返されない場合、それはFalse
値です。 これらのnextステートメントはどちらもTrue
評価されます。,
$data = @('red','green','blue') if ( $data -eq 'green' ) { 'Green was found' } if ( $data -ne 'green' ) { 'And green was not found' }
$null
のテストについて話すとき、私は一瞬でこれを再訪します。
-match
-match
演算子は、コレクション内の各アイテムの一致を試みます。
PS> $servers = @( 'LAX-SQL-01' 'LAX-API-01' 'ATX-SQL-01' 'ATX-API-01' ) PS> $servers -match 'SQL' LAX-SQL-01 ATX-SQL-01
-match
を単一の値で使用すると、特別な変数$Matches
に一致情報が入力されます。 配列がこのように処理される場合、これは当てはまりません。
Select-String
でも同じアプローチを取ることができます。,
$servers | Select-String SQL
私は詳しく見てみましょうSelect-String
、-match
そして$matches
正規表現を使用する多くの方法と呼ばれる別の投稿の変数。
$nullまたは空
$null
または空の配列のテストは難しい場合があります。 配列を持つ一般的なトラップは次のとおりです。
一見すると、このステートメントは動作するはずです。
if ( $array -eq $null) { 'Array is $null' }
しかし、私はちょうど-eq
配列内の各項目をチェックする方法を調べました。, したがって、単一の$null値を持ついくつかの項目の配列を持つことができ、評価されます$true
$array = @('one',$null,'three') if ( $array -eq $null) { 'I think Array is $null, but I would be wrong' }
これが、$null
演算子の左側に配置することがベストプラクティスである理由です。 これにより、このシナリオは問題になりません。
if ( $null -eq $array ) { 'Array actually is $null' }
a$null
配列は空の配列と同じものではありません。 配列があることがわかっている場合は、その中のオブジェクトの数を確認します。, 配列が$null
の場合、カウントは0
になります。
if ( $array.count -gt 0 ) { 'Array is not empty' }
ここにはもう一つ気をつけるべき罠があります。 あなたが使用することができますcount
そのオブジェクトがPSCustomObject
でない限り、単一のオブジェクトがある場合でも、PSCustomObject
。 これはPowerShell6.1で修正されたバグです。 それは良いニュースですが、多くの人がまだ5.1にいて、それに気をつける必要があります。
PS> $object = @{Name='TestObject'} PS> $object.count $null
PowerShellをまだ使用している場合5.,1、ラップ、オブジェクト配列でチェックイン前にカウントへの正確な数です。
if ( @($array).count -gt 0 ) { 'Array is not empty' }
完全に安全に再生するには、$null
、カウントを確認してください。
if ( $null -ne $array -and @($array).count -gt 0 ) { 'Array is not empty' }
All-eq
私は最近、誰かが配列内のすべての値が特定の値と一致することを確認する方法を尋ねるのを見ました。 Redditユーザー/u/bisには、誤った値をチェックして結果を反転させるこの巧妙な解決策がありました。,
$results = Test-Something if ( -not ( $results -ne 'Passed') ) { 'All results a Passed' }
配列への追加
この時点で、配列にアイテムを追加する方法を疑問に思い始めています。 簡単な答えは、できないということです。配列はメモリ内の固定サイズです。 それを拡張するか、単一のアイテムを追加する必要がある場合は、新しい配列を作成し、古い配列からすべての値をコピーする必要があります。 これは高価に聞こえ、多くの作業のように聞こえますが、PowerShellは新しい配列を作成する複雑さを隠します。
配列追加
新しい配列を作成するために、配列と共に加算演算子を使用することができます。, したがって、これら二つの配列を考えると:
$first = @( 'Zero' 'One' ) $second = @( 'Two' 'Three' )
新しい配列を取得するためにそれらを一緒に追加することができます。
PS> $first + $second Zero One Two Three
Plus equals+=
新しい配列を作成し、次のようにアイテムを追加できます。
$data = @( 'Zero' 'One' 'Two' 'Three' ) $data += 'four'