Сортировка PowerShell по 2-му индексу

#regex #powershell #sorting #match #sort-object

#регулярное выражение #powershell #сортировка #совпадение #сортировка-объект

Вопрос:

Я пытаюсь отсортировать серверы по 2-му индексу имени. Имена серверов берутся из путей к файлам, где они являются базовым именем файла. Я знаю, что у Select-Object есть параметр -Index, но я не думаю, что это сработает. Я предполагаю, что лучший подход — использовать регулярное выражение PowerShell типа «(?: ^ a-z))». Это возвращает несортированный список, и я все еще ищу шаблон, который будет сортировать по 2-му индексу.

Пример предполагаемого вывода

  • Сгруппируйте серверы по имени CC или DD
 Server        
------        
ABCCWS01
CDCCWS01
ABDDWS01
CDDDWS01
  

Текущий вывод

  • Сортирует в алфавитном порядке по имени свойства
 $servers = Get-Item -Path
C:ABDDWS01.ServerData, 
C:ABCCWS01.ServerData, 
C:CDCCWS01.ServerData, 
C:CDDDWS01.ServerData | Group BaseName -AsHashtable

foreach($computer in $servers.GetEnumerator() | Sort-Object -Property name)
{ ...DoSomething... }

Server        
------        
ABCCWS01
ABDDWS01
CDCCWS01
CDDDWS01
  

Затем я попытался реализовать регулярное выражение PowerShell. Но я застрял на том, как правильно использовать это для сортировки по 2-му индексу. Этот пример не влияет и возвращает список без сортировки. Я пробовал добавлять разные шаблоны в конце «(?: ^ a-z))». Пока мои попытки возвращают либо несортированный список, либо просто сегмент списка.
Я поискал в Google и попробовал много разных вещей. Если кто-то еще хочет помочь разобраться в этом, это очень ценится.

 Sort-Object -Property @{Expression={[RegEx]::Match($_.basename, "(?:^a-z))")}}
  

Ответ №1:

Sort-Object работает путем «ранжирования» каждого ввода в соответствии с результирующим значением вычисления одного или нескольких выражений свойства для каждого элемента ввода — в вашем существующем примере на основе значения name свойства.

Как вы уже выяснили, выражения свойств не должны быть значением какого-либо существующего свойства — они могут состоять из чего угодно — просто передайте блок сценария вместо имени свойства:

 ... |Sort-Object -Property {$_.name[1]}
  

Причина, по которой это не работает в вашем примере, заключается в том, что выражение [RegEx]::Match($_.basename, "(?:^a-z))") возвращает [System.Text.RegularExpressions.Match] объект — и их нельзя осмысленно сравнивать друг с другом.

Если вы измените выражение, чтобы вместо этого преобразовать его в строку (например, соответствующее значение), это сработает:

 ... |Sort-Object -Property @{Expression={[RegEx]::Match($_.basename, "(?:^a-z))").Value}}
# or
... |Sort-Object -Property {[RegEx]::Match($_.basename, "(?:^a-z))").Value}
  

Комментарии:

1. Круто, что работает, вроде как. В ходе многих испытаний я наткнулся на что-то вроде ваших примеров, но, полагаю, на самом деле я использовал их неправильно. Я использовал {$_.name[2]} и он отсортирован по 2-му индексу. Теперь они сгруппированы вместе, как я и предполагал, но не по порядку внутри группы. Возможно, я ищу невозможное. Может быть, мне нужно отсортировать его во второй раз после их группировки? Я буду продолжать играть 🙂 Спасибо за ваш быстрый ответ, Матиас!

2. @JessicaNations Какова цель Group-Object вызова в вашем исходном примере? BaseName Значения, используемые в примере, все разные, поэтому каждая группа в любом случае будет содержать только один файл?

3. Я не уверен, как еще использовать BaseName термин без Group , чтобы создать -asHashTable

4.@JessicaNations Но нужна ли вам хэш-таблица? Как только вы это сделаете, $ht = $ht.GetEnumerator() |Sort Name это все равно больше не будет хэш-таблицей — это просто массив пар ключ-значение. Не стесняйтесь обращаться ко мне в Twitter / gitter, если вам нужна помощь 🙂

5. @JessicaNations Отлично! Кстати, вам не нужен GetEnumerator() вызов, $servers это уже массив, и foreach он все равно будет правильно повторяться 🙂