Соответствие регулярному выражению PowerShell Y или Z - PullRequest
3 голосов
/ 05 марта 2019

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

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

PC1-FOO1234567
PC2-FOO1234567/FOO98765

Это работает для второго примера:

'PC2-FOO1234567/FOO98765' -match 'FOO(.*?)\/FOO(.*?)\z'

Позволяет мне получить доступ к соответствующим строкам, используя $matches[1] и $matches[2], и это здорово.

Это явно не работает для первого примера. Я подозреваю, что мне нужен какой-то способ сопоставления либо на /, либо на конце строки, но я не уверен, как это сделать, и в итоге получу желаемое совпадение.

Предложения

Ответы [ 3 ]

4 голосов
/ 05 марта 2019

Вы можете использовать

'FOO(.*?)(?:/FOO(.*))?$'

Это будет соответствовать FOO, затем захватить 0 или более символов как можно меньше в Группе 1, а затем попытаться по желанию сопоставить последовательность шаблонов: /FOO любые 0 или более символов, как можно больше, заносятся в Группу 2, после чего следует конец строки.

См. демонстрацию regex

Подробности

  • FOO - буквенная подстрока
  • (.*?) - Группа 1: любой ноль или более символов, кроме новой строки, как можно меньше
  • (?:/FOO(.*))? - необязательная группа без захвата, соответствующая 1 или 0 повторениям:
    • /FOO - буквенная подстрока
    • (.*) - группа 2: любые 0+ символов кромеперевод строки как можно больше (* жадный)
  • $ - конец строки.

enter image description here

2 голосов
/ 05 марта 2019

Чтобы предложить более краткую альтернативу с оператором -split , которая устраняет необходимость доступа к $Matches впоследствии для извлечения чисел:

PS> 'PC1-FOO1234568', 'PC2-FOO1234567/FOO98765' -split '(?:^PC\d+-|/)FOO' -ne ''
1234568  # single match from 1st input string
1234567  # first of 2 matches from 2nd input string
98765

Примечание: -split всегда возвращает массив [string[]], даже если возвращается только 1 строка; Строки результата из нескольких входных строк объединяются в один плоский массив.

  • ^PC\d+-|/ соответствует PC, за которым следуют 1 или более (+) цифр (\d) в начале строки (^) или (* 1023) *) a / char., который соответствует PC2-FOO в начале и /FOO.

    • (?:...), нефиксирующее подвыражение , должно использоваться для предотвращения -split включения того, что подвыражение совпало в массиве результатов.
  • -ne '' отфильтровывает пустых элементов, которые являются результатом входных строк начиная с с разделителем.


Чтобы узнать больше об операторе -split на основе регулярных выражений и о том, как он более мощный, чем метод .NET String.Split() на основе строковых литералов, см. этот ответ .

2 голосов
/ 05 марта 2019

[edit - удалить ненужный канал в Where-Object.спасибо mklement0 за это![* ухмыляется *]]

это несколько иной подход.он разделяется на foo, затем заменяет ненужное / ничем и, наконец, отфильтровывает любую строку, содержащую буквы.

Чистые решения регулярных выражений, предлагаемые другими, скорее всего, будут быстрее, но это может быть немного легче понять - и, следовательно, поддерживать.[ ухмылка ]

# fake reading in a text file
#    in real life, use Get-Content
$InStuff = @'
PC1-FOO1234567
PC2-FOO1234567/FOO98765
'@ -split [environment]::NewLine

$InStuff -split 'foo' -replace '/' -notmatch '[a-z]'

вывод ...

1234567
1234567
98765
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...