PowerShell: Where-Object -MATCH 内の正規表現に配列値を代入する方法

PowerShell: Where-Object -MATCH 内の正規表現に配列値を代入する方法

-match以下の条件で、配列から文字列値を取得して正規表現に挿入する際に問題が発生していますWhere-Object

$ordArr = @("001", "005", "002", "007")

for ($i = 0; $i -le $ordArr.Length) {
  get-childitem -file -recurse |
    where-object {$_.BaseName -match "^$ordArr[$i].*$"} |
      ForEach-Object {echo $_}

  $i = ($i + 2)
}

単独で入力する場合$ordArr[$i](つまり、関数の外部で呼び出す場合) Where-Object、期待される文字列値が返されます。

私も試してみました

  • ... -match "^${ordArr[$i]}.*$ ... "
  • ... -match "^${ordArr[$[tick mark]{i[tick mark]}]}.*$ ... "

ティック マーケットと中括弧を使用したその他のさまざまな組み合わせ。ただし、$ordArrコマンドに代入される文字列値を から取得できません。

中括弧とチェックマークの組み合わせに応じて、何も返されないか、すべてが返されます。また、001から を$ordArr正規表現に手動で入力すると... -match "^001.*$" ...、期待どおりのファイルが返されます。

では、配列の値を 内の正規表現条件に挿入するにはどうすればよいでしょうかWhere-Object ... -match ...?

ありがとう!

答え1

正規表現パターンでは、意図したとおりに文字列が補間されません。

"^$ordArr[$i].*$"}結果的に^001 005 002 007[0].*$

あなたは部分式演算子 $()$int1 + $int2計算 ( )、メンバー アクセス ( $something.Path)、インデックス アクセス ( $array[1]) などの式を、文字列などの別の式内で使用する場合。

あなたの場合は、$ordArr[$i]サブ式に入力する必要があります:

"^$($ordArr[$i]).*$"

見る:MSFT: 部分式演算子 $( )

さらに、 orループGet-ChildItem内で同じ場所を使用することは避けてください。例では、同じ項目に対して Get-ChildItem を 4 回再帰的に呼び出しています。forforeach

私のおすすめ

私の提案は、パターンを構築するために配列を複数回ループするのではなく、結合された正規表現パターンを 1 つに定義することです。これは他のアプローチよりもはるかに高速です。

$ordArr = @('001', '005', '002', '007')

# build a combined regex pattern 
#   this time we don't need a subexpression operator, since we don't access any member or index from $_
$regexPattern = ($ordArr | ForEach-Object { "^$_.*$" }) -join '|'

Get-ChildItem -File -Recurse | Where-Object {
    $_.BaseName -match  $regexPattern 

    # as alternative and to avoid saving anything to the automatic variable $matches (-> better performance)
    # but not idiomatic Powershell:
    # [regex]::IsMatch($_.BaseName, $regexPattern)
}

関連情報