Как я могу соединить массив от промежуточной точки до конца или до конца - 1? - PullRequest
1 голос
/ 24 сентября 2019

Мне нужно сравнить файлы в двух структурах каталогов.База каталогов начинается со второго элемента в свойстве DirectoryName.Однако я не знаю, сколько дополнительных элементов будет на пути.Использование 999 в качестве конца диапазона работает, но, безусловно, есть лучший способ сделать это.

PS>Get-ChildItem -File -Recurse -Path "$Env:USERPROFILE\Documents" |
    ForEach-Object {
        $_.DirectoryName.Split('\')[2..999] -join '\'
    }

Использование диапазона [2..-1] не работает.

Ответы [ 2 ]

0 голосов
/ 24 сентября 2019

Другой способ, пропустить первые 2.

Get-ChildItem -File -Recurse -Path $Env:USERPROFILE\Documents |
  ForEach { ($_.DirectoryName.Split('\') | select -skip 2) -join '\' }

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

Get-ChildItem -File -Recurse -Path "$Env:USERPROFILE\Documents" | 
  foreach { $_.fullname.replace('C:\Users\','')}
0 голосов
/ 24 сентября 2019

[2..-1] не работает, поскольку массив индексов , созданный с помощью .., оператор диапазона , в данном случае 2, 1, 0, -1 это не то, что вы хотели.

К сожалению, в PowerShell Core 7.0.0-preview.4, единственный способ сослаться на все оставшиеся элементы (или всеОстальные элементы, кроме last (N ), выражаются на основе количества элементов массива , которое требует, чтобы вы захватили массив в переменную first :

Get-ChildItem -File -Recurse -Path "$Env:USERPROFILE\Documents" |
    ForEach-Object {
        $components = $_.DirectoryName.Split('\')
        $components[2..($components.Count-1)] -join '\'
    }

Перспективы на будущее: Предоставление удобного синтаксиса индекса, который позволяет ссылаться на все оставшиеся элементы (с [2..]), а также на все остальные элементы, кроме последнего $n (счто-то вроде [2..@-$n]), является предметом этого запроса функции на GitHub .

Примечание: решение на основе конвейера через Select-Object -Skip 2, как показано в ответе js2010 , удобно, но заметно медленнее , чем решение для нарезки массивов.


Что касается того, что вы пытались :

Предоставление фиксированной верхней границы, такой как 999, которая известна всегдабыть выше, чем истинное число элементов работает ЕСЛИ И ТОЛЬКО ЕСЛИ (а) эта граница известна и (б) достаточно мала, чтобы не вызывать проблем с памятью / производительностью.

Поэтому, используя что-то вроде 2..([int]::MaxValue-1) это не вариант.

(На практике в PowerShell Core самый высокий индекс, который вы можете использовать, это [int]::MaxValue - 1048576 ([int]::MaxValue - [Math]::Pow(2, 20))) - но генерирует массив с таким количеством элементов (в качестве индексов) с .. непомерно медленным и интенсивно использует память).


Если производительность имеет первостепенное значение , используйте решение на основе .Substring(), в котором просто пропущен путьпрефикс, основанный на пути ввода:

$inputPath = "$Env:USERPROFILE\Documents"

# Determine the length of the prefix 
# comprising the input path's first 2 path components.
$prefixLength = ($inputPath -replace '^(.+?\\.+?\\).*', '$1').Length

Get-ChildItem -File -Recurse -Path $inputPath |
 ForEach-Object {
   $_.DirectoryName.Substring($prefixLength)
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...