Я ищу способ отфильтровать список строк в powershell по регулярному выражению, а затем сгруппировать и отсортировать по одной из групп захвата.

Представьте, что мой список такой:

bogus0
ACBXYZ-0000 hello
bogus1
ACBXYZ-0000 hello again
bogus2
ACBXYZ-0001 world
bogus3
ACBXYZ-0001 world

Сначала я сделал это:

$list | select-string "^(ACBXYZ-\d+)(.*)"

Какие выводы

ACBXYZ-0000 hello
ACBXYZ-0000 hello again
ACBXYZ-0001 world
ACBXYZ-0001 world

Тогда я сделал это:

$list | select-string "^(ACBXYZ-\d+)(.*)" | % { "$($_.Matches[0].Groups[1].Value), $($_.Matches[0].Groups[2].Value.Trim(' ,-'))" } | sort | group | select name

Какие выводы

Name
----
ACBXYZ-0000, hello
ACBXYZ-0000, hello again
ACBXYZ-0001, world

Но на самом деле я хотел бы вывести это:

Name
----
ACBXYZ-0000, hello
ACBXYZ-0001, world

так как сообщение после номера приятно иметь, но не очень важно.

Есть идеи?

PS: я смог добиться этого с помощью более сложного сценария, но я искал однострочник.

1 ответ1

0

Вам нужна хеш-таблица для хранения ваших результатов. Хеш-таблица представляет собой набор пар ключ-значение. В вашем случае ключами будут строки «ACBXYZ-0000», а значениями будут строки "привет". Ключи в хеш-таблицах уникальны, и это именно то, что нам нужно здесь.

Например:

$myHash = @{}
$myHash["ACBXYZ-0001"] = "hi there"  # set a value
Write-Output $myHash["ACBXYZ-0001"]  # retrieve the value

Я переписал ваш скрипт для использования хеш-таблицы здесь:

$list = gc text.txt
$out = @{}
$list | select-string "^(ACBXYZ-\d+)(.*)" | 
    % { $out[$_.Matches[0].Groups[1].Value] = $_.Matches[0].Groups[2].Value.Trim(' ,-') }
$out 

Это дает это:

Name                           Value                                                                                                           
----                           -----                                                                                                           
ACBXYZ-0000                    hello again                                                                                                     
ACBXYZ-0001                    world                                                                                                           

Вы можете видеть, что второй «ACBXYZ-0000» перезаписал первый. Если вам это не нравится, перед сохранением ключа вы можете проверить, существует ли он в хеш-таблице уже с $out.ContainsKey() .

Я оставлю вам решать, как выводить результаты в виде отсортированного списка строк. Дайте мне знать, если у вас есть проблемы.

Ради интереса, я также переписал ваш сценарий так, чтобы я делал это так:

$list = gc text.txt
$out = @{}
$list | % {
    if ($_ -match "^(ACBXYZ-\d+)(.*)") 
    { 
        $out[$matches[1]] = $matches[2].Trim(' ,-') 
    } 
}
$out

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .