Вопрос о регулярном выражении Powershell. Экранирующая скобка

Весь день ломаю голову над этим, и я приближаюсь, но не совсем туда. У меня есть небольшое подмножество моего гораздо большего сценария только для части регулярного выражения. Вот сценарий на данный момент:

  
  $CCI_ID = @(
  "003417 AR-2.1"
  "003425 AR-2.9"
  "003392 AP-1.12"
  "009012 APP-1(21).1"
  )


  [regex]::matches($CCI_ID, '(\d{1,})|([a-zA-Z]{2}[-][\d][\(?\){0,1}[.][\d]{1,})') | 
      ForEach-Object {
        if ($_.Groups[1].Value.length -gt 0){
          write-host $('CCI-' + $_.Groups[1].Value.trim())}
        else{$_.Groups[2].Value.trim()}
      }  

CCI-003417
AR-2.1
CCI-003425
AR-2.9
CCI-003392
AP-1.12
CCI-009012
PP-1(21
CCI-1


The output is correct for all but the last one. It should be:
      
      CCI-009012
      APP-1(21).1

Thanks for any advice.

 

В качестве отступления: если вы передадите массив в качестве первого аргумента (входной строки) в [regex]::Matches(), PowerShell неявно преобразует его в строку, т. е. преобразует его в одну строку, содержащую (строковые) элементы массива, разделенные пробелом. каждый.

mklement0 11.01.2023 01:53
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
64
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вместо того, чтобы описывать и количественно определять (необязательные) открывающую и закрывающую скобки по отдельности, сгруппируйте их вместе, а затем сделайте всю группу необязательной:

(?:\(\d+\))?

Таким образом, весь шаблон выглядит так:

[regex]::Matches($CCI_ID, '(\d{1,})|([a-zA-Z]{2,3}[-][\d](?:\(\d+\))?[.][\d]{1,})')

Как вы видите здесь, выражения Regex могут стать очень сложными и нечитаемыми.
Поэтому часто рекомендуется рассматривать проблему с двух разных точек зрения:

  • Попробуйте сопоставить нужные детали или
  • Попробуйте сопоставить части, которые вам не нужны

В вашем случае, вероятно, проще сопоставить ту часть, которую вы не хотите: разделитель, пробел и разделить строку на это, чего, по-видимому, вы хотите достичь:

$CCI_ID | Foreach-Object {
    $Split = $_ -Split '\s+', 2
    'CCI-' + $Split[0]
    $Split[1]
}

$_ -Split '\s+', 2, разбивает соответствующую строку на основе 1 или более пробелов (где вы также можете рассмотреть буквальное пространство: -Split ' '). , 2 предотвратит разделение строки более чем на 2 части. Это означает, что вторая часть не будет разделена, даже если она содержит пробелы.

Это был отличный ответ, и я буду использовать эту логику в будущем. Я проголосовал за вас по этой причине.

Matt Williamson 13.01.2023 22:07

В своем шаблоне вы используете чередование |, но, глядя на данные примера, вы можете вместо этого сопоставить 1 или более пробелов после него.

Если есть совпадение с шаблоном, значение группы 1 уже содержит 1 или более цифр, поэтому вам не нужно проверять Value.length

Шаблон с необязательными цифрами в скобках:

\b(\d+)\s+([a-zA-Z]{2,}-\d(?:\(\d+\))?\.\d+)\b

Посмотрите демоверсию regex101.

$CCI_ID = @(
"003417 AR-2.1"
"003425 AR-2.9"
"003392 AP-1.12"
"009012 APP-1(21).1"
)

[regex]::matches($CCI_ID, '\b(\d+)\s+([a-zA-Z]{2,}-\d(?:\(\d+\))?\.\d+)\b') |
        ForEach-Object {
            write-host $( 'CCI-' + $_.Groups[1].Value.trim() )
            write-host $_.Groups[2].Value.trim()
        }

Выход

CCI-003417
AR-2.1
CCI-003425
AR-2.9
CCI-003392
AP-1.12
CCI-009012
APP-1(21).1

Другие вопросы по теме