Вопрос о регулярном выражении 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
Конечные и Readonly классы в PHP
Конечные и Readonly классы в PHP
В прошлом, когда вы не хотели, чтобы другие классы расширяли определенный класс, вы могли пометить его как final.
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
Если вы уже умеете работать с React, создание мобильных приложений для iOS и Android - это новое приключение, в котором вы сможете применить свои...
БЭМ: Конвенция об именовании CSS
БЭМ: Конвенция об именовании CSS
Я часто вижу беспорядочный код CSS, особенно если проект большой. Кроме того, я совершал эту ошибку в профессиональных или личных проектах и...
Революционная веб-разработка ServiceNow
Революционная веб-разработка ServiceNow
В быстро развивающемся мире веб-разработки ServiceNow для достижения успеха крайне важно оставаться на вершине последних тенденций и технологий. По...
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Заголовок веб-страницы играет наиболее важную роль в SEO, он помогает поисковой системе понять, о чем ваш сайт.
Конфигурация Jest в angular
Конфигурация Jest в angular
В этой статье я рассказываю обо всех необходимых шагах, которые нужно выполнить при настройке jest в angular.
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

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