Подтвердить что ты не робот

Как извлечь значение regex backreference/match в Powershell

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

select-string -path *.txt -pattern "subject=([A-Z\.]+),"

Некоторые примеры данных:

blah blah subject=THIS.IS.TEST.DATA, blah blah blah

Я хочу, чтобы иметь возможность извлекать только фактическое содержимое объекта (т.е. строку "THIS.IS.TEST.DATA" ). Я пробовал это:

select-string -path *.txt -pattern "subject=([A-Z\.]+)," | %{ $_.Matches[0] }

Но свойство "Матчи" всегда равно нулю. Что я делаю неправильно?

4b9b3361

Ответ 1

Я не знаю, почему ваша версия не работает. Он должен работать. Вот более уродливая версия, которая работает.

$p = "subject=([A-Z\.]+),"
select-string -path *.txt -pattern $p | % {$_ -match $p > $null; $matches[1]}

Объяснение:

-match является оператором сопоставления регулярного выражения:

>"foobar" -match "oo.ar"
True

> $null просто подавляет запись True в вывод. (Попробуйте удалить его.) Существует командлет, который делает то же самое, имя которого я не помню в данный момент.

$matches -match - это магическая переменная, которая содержит результат последней операции -match.

Ответ 2

В PowerShell V2 CTP3 реализовано свойство Matches. Так будет работать следующее:

select-string -path *.txt -pattern "subject=([A-Z\.]+)," | %{ $_.Matches[0].Groups[1].Value }

Ответ 3

Еще один вариант

gci *.txt | foreach { [regex]::match($_,'(?<=subject=)([^,]+)').value }

Ответ 4

Проблема с кодом, который вы вводите, заключается в том, что select-string не пропускает фактический объект Regex. Вместо этого он передает другой класс, называемый MatchInfo, который не имеет актуальной информации соответствия регулярных выражений.

Если вы хотите запускать регулярное выражение только один раз, вам придется свернуть свою собственную функцию, которая не слишком сложна.

function Select-Match() {
  param ($pattern = $(throw "Need a pattern"), 
         $filePath = $(throw "Need a file path") )
  foreach ( $cur in (gc $filePath)) { 
    if ( $cur -match $pattern ) { 
      write-output $matches[0];
    }
  }
}

gci *.txt | %{ Select-Match "subject=([A-Z\.]+)," $_.FullName }

Ответ 5

Узнав много из всех других ответов, я смог получить то, что хочу, используя следующую строку:

gci *.txt | gc | %{ [regex]::matches($_, "subject=([A-Z\.]+),") } | %{ $_.Groups[1].Value }

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

Ответ 7

Команда Select-String возвращает переменную MatchInfo, а не переменную "string". Я потратил несколько часов на то, чтобы найти это на форумах и официальном сайте без везения. Я все еще собираю информацию. Путь к этому состоит в том, чтобы явно объявить строковую переменную для хранения результата, возвращаемого из Select-String, из вашего примера:

[строка] $foo = select-string -path *.txt -pattern "subject = ([A-Z.] +),"

Переменная $foo теперь является строкой, а не объектом MatchInfo.

Надеюсь, что это поможет.

ps5 powershell версия 5 манипуляции строковыми строками

Ответ 8

Еще одна вариация, соответствующая 7 цифрам в строке

echo "123456789 hello test" | % {$_ -match "\d{7}" > $null; $matches[0]}

возвращает: 1234567