Как выбрать несколько столбцов и расширить свойства с помощью powershell select-string -Allmatch?

Я ищу набор текстовых файлов (*.sql) на наличие 8-значных чисел, начинающихся с 9. В файле может быть несколько экземпляров этих чисел, а также несколько экземпляров в каждой строке файла. Я только хочу, чтобы на выходе отображалось уникальное появление каждого 8-значного числа в каждом файле. Это то, что у меня есть до сих пор:

Select-String "9[0-9]{8}" "*.sql" -AllMatches | Select-Object FileName, @{N="Value";E={ $_.matches |  %{$_.groups[0].value}}} | Select-Object  -unique FileName,Value  

И мой вывод выглядит так:

FileName                       Value
--------                       -----

File1.sql                      907520714
File1.sql                      {907500507, 907520700, 907520701, 907520703...} 
File1.sql                      {907520725, 907520727, 907520728, 907520729} 
File1.sql                      990140600
File2.sql                      990319161
File2.sql                      {990603919, 990603925, 990603926} 
File2.sql                      {991100103, 991100103}
File2.sql                      {990700023, 990700504, 990700521, 990740520...} 
File3.sql                      907500044

так далее....

Что я хотел бы сделать, так это расширить массивы, чтобы при передаче через select -unique я фактически получал только уникальные 8-значные числа, содержащиеся в каждом файле.

Это то, что я хотел бы:

FileName                       Value
--------                       -----

File1.sql                      907520714
File1.sql                      907500507
File1.sql                      907520700
File1.sql                      907520701
File1.sql                      907520703 
File1.sql                      907520725
File1.sql                      907520727
File1.sql                      907520728
File1.sql                      907520729 
File1.sql                      990140600
File2.sql                      990319161
File2.sql                      990603919
File2.sql                      990603925
File2.sql                      990603926 
File2.sql                      991100103
File2.sql                      990700023
File2.sql                      990700504
File2.sql                      990700521
File2.sql                      990740520 
File3.sql                      907500044

так далее...

Как я могу это сделать? И можно ли улучшить мою текущую команду powershell?

Спасибо!


person RayBan    schedule 15.05.2014    source источник


Ответы (2)


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

Select-String "9[0-9]{8}" "*.sql" -AllMatches | `
    Select-Object FileName, @{N="Value";E={ $_.matches | %{$_.groups[0].value}}} | `
    Select-Object  -unique FileName,Value 

Ваша исходная команда выдает одну строку вывода для каждого MatchInfo, возвращаемого командлетом Select-String. MatchInfo представляет совпадающую строку текстового файла. Я полагаю, что вы получаете массив значений, когда одна строка в файле содержит более одного совпадающего значения.

Я пересмотрел его, чтобы уточнить, что нам нужен один объект вывода для каждого RegexMatch в каждом MatchInfo, то есть один объект вывода для каждого совпадающего значения.

Select-String "9[0-9]{8}" "*.sql" -AllMatches | `
    Foreach-Object { 
        # $_ is MatchInfo for each matching line in file
        $fileName = $_.FileName 
        $_.Matches | Foreach-Object { 
            # $_ is RegexMatch for each match in line
            $_ | Select-Object -Property @{N="FileName";E={$fileName} },Value
        } 
    } | Select-Object  -unique FileName,Value 
person James    schedule 15.05.2014
comment
Привет, спасибо за быстрый ответ и объяснение. Вышеприведенное прекрасно работает, плюс я смог расширить ваш код, включив в него некоторые другие свойства, которые я не включил в свой пример выше. (На самом деле я ищу несколько подкаталогов, и мне нужно извлечь имя родительского каталога, чтобы включить его в окончательный выбор) - person RayBan; 21.05.2014

Ладно, в основном убегаешь от того, что имеешь. Я делаю цикл ForEach для всех совпадений, найденных Select-String, и группирую их по имени файла. Затем для каждого файла я перебираю группы, расширяющие Matches, а затем беру только уникальные значения для совпадающего текста. Для каждого значения я вывожу объект, содержащий имя файла и совпадающее значение.

ForEach($File in Select-String "9[0-9]{8}" "*.sql" -AllMatches | Group FileName){
    $File.group|select -expand matches|Select Value -Unique|%{
        new-object PSObject -property @{
            FileName=$File.Name
            Match=$_.value
        }
    }
}
person TheMadTechnician    schedule 15.05.2014
comment
Ваш код работает, но у меня возникли проблемы с его расширением, чтобы включить имя родительского каталога файлов, которые я ищу в нескольких подкаталогах (как часть нового объекта) - person RayBan; 21.05.2014