PowerShell: So ersetzen Sie einen Array-Wert durch einen regulären Ausdruck innerhalb von Where-Object -MATCH

PowerShell: So ersetzen Sie einen Array-Wert durch einen regulären Ausdruck innerhalb von Where-Object -MATCH

Ich habe Probleme, einen Zeichenfolgenwert aus einem Array abzurufen, um ihn in den regulären Ausdruck unter der folgenden -matchBedingung einzufügen 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)
}

Wenn ich es selbst eingeben soll $ordArr[$i](also außerhalb der Where-ObjectFunktion aufrufe), gibt es die erwarteten Stringwerte zurück.

Ich habe auch versucht

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

und andere verschiedene Kombinationen mit Tick-Märkten und Klammern. Ich kann den Zeichenfolgenwert jedoch nicht aus dem $ordArrBefehl ersetzen.

001Abhängig von der Kombination aus Klammern und Häkchen gibt es entweder nichts oder alles zurück. Wenn ich manuell von $ordArrin den regulären Ausdruck eingebe , ... -match "^001.*$" ...werden die erwarteten Dateien zurückgegeben.

Wie kann ich also einen Wert aus einem Array in die darin enthaltene Regex-Bedingung einfügen Where-Object ... -match ...?

Danke!

Antwort1

Ihr Regex-Muster interpoliert die Zeichenfolge nicht wie beabsichtigt.

"^$ordArr[$i].*$"}führt zu^001 005 002 007[0].*$

Sie müssen dieUnterausdrucksoperator $()$int1 + $int2wenn Sie Ausdrücke wie Berechnungen ( ), Mitgliedszugriff ( $something.Path), Indexzugriff ( $array[1]) usw. innerhalb eines anderen Ausdrucks wie einem String verwenden möchten .

In Ihrem Fall müssen Sie Folgendes $ordArr[$i]in einen Unterausdruck einfügen:

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

Sehen:MSFT: Unterausdrucksoperator $( )

Get-ChildItemDarüber hinaus sollten Sie die Verwendung für denselben Standort innerhalb einer foroder Schleife vermeiden foreach. In Ihrem Beispiel rufen Sie Get-ChildItem rekursiv 4 Mal für dieselben Elemente auf.

Mein Vorschlag

Mein Vorschlag ist, ein kombiniertes Regex-Muster zu definieren, um ein einzelnes zu erhalten, anstatt mehrere Schleifen über ein Array durchzuführen, um ein Muster zu erstellen. Dies ist viel schneller als andere Ansätze.

$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)
}

verwandte Informationen