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]}]}.*$ ... "

и другие смешанные комбинации с использованием тиковых рынков и фигурных скобок. Однако я не могу получить строковое значение из to, $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: Оператор подвыражения $( )

Кроме того, следует избегать использования Get-ChildItemfor для одного и того же местоположения внутри цикла foror foreach. В вашем примере вы вызываете Get-ChildItem рекурсивно 4 раза для одних и тех же элементов.

Мое предложение

Мое предложение — определить комбинированный шаблон регулярных выражений, чтобы получить один вместо того, чтобы проходить несколько раз по массиву для построения шаблона. Это намного быстрее других подходов.

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

Связанный контент