2016-11-09 2 views
1

Вот некоторые примеры строк мне нужно разобрать:Регулярное выражение: группа захвата может не существовать. Как мне написать?

1 - Cream Soda (0.99) 
5 - Potato Chips (2.50) 
12 - Atlantic Salmon 

Я хочу, чтобы захватить первую цифру, название продукта и цену, включая скобки. Иногда цена и соответствующие круглые скобки не существуют.

Я пришел с этим регулярным выражением:

/(\d+)\s+-\s*(.+)\s+(\(.*\))/ 

, которая работает только тогда, когда существуют все три группы. Я также пробовал:

/(\d+)\s+-\s*(.+)\s+(\(.*\))?/ 

но его не лучше.

Как сделать третью группу захвата опцией?

Это в javascript, если это имеет значение.

ответ

1

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

/^(\d+)\s+-\s*(.*?)(?:\s+(\([^()]+\)))?$/ 

Смотрите regex demo

Детали:

  • ^ - начало строки
  • (\d+) - Группа 1 захватив первые 1 или более цифр
  • \s+ - 1 или более пробельные
  • - - дефис
  • \s* - 0+
  • пробельные символы
  • (.*?) - Группа 2 захвата любых 0+ символов, но, как мало, как это возможно
  • (?:\s+(\([^()]+\)))? - необязательная группа, соответствующей 1 или 0 последовательности:
    • \s+ - 1+ пробельные символы
    • (\([^()]+\)) - Группа 3 захвата (, 1+ обугливается, кроме ( и ), то )
  • $ - конец строки.

var strs = ["1 - Cream Soda (0.99)", "5 - Potato Chips (2.50)", "12 - Atlantic Salmon"]; 
 
var re = /^(\d+)\s+-\s*(.*?)(?:\s+(\([^()]+\)))?$/; 
 
for (var s of strs) { 
 
    var m = re.exec(s); 
 
    if (m) { 
 
    console.log("1: " + m[1] + ", 2: " + m[2] + (m[3] ? ", 3: " + m[3] : "")); 
 
    } 
 
}

+1

Я люблю мощь и гибкость regex, но это определенно не моя сильная сторона. Это делает трюк! – Octopus

1

Вы можете сделать 2-ю группу ленивым и использовать конец строки в качестве альтернативного матча в 3-й группе:

(\d+)\s+-\s*(.+?)\s*(\(.*\)|$) 

RegEx Demo

Смежные вопросы