#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
он все равно будет правильно повторяться 🙂