Regex, чтобы соответствовать только запятые не в скобках? - PullRequest
25 голосов
/ 27 января 2012

У меня есть строка, которая выглядит примерно так:

12,44,foo,bar,(23,45,200),6

Я хотел бы создать регулярное выражение, соответствующее запятым, но только запятым, которые не заключены в скобки (в примеревыше, все запятые, кроме двух после 23 и 45).Как бы я это сделал (регулярные выражения Java, если это имеет значение)?

Ответы [ 4 ]

54 голосов
/ 27 января 2012

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

Pattern regex = Pattern.compile(
    ",         # Match a comma\n" +
    "(?!       # only if it's not followed by...\n" +
    " [^(]*    #   any number of characters except opening parens\n" +
    " \\)      #   followed by a closing parens\n" +
    ")         # End of lookahead", 
    Pattern.COMMENTS);

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

6 голосов
/ 15 мая 2014

Павел, воскрешает этот вопрос, потому что у него было простое решение, которое не было упомянуто.(Нашел свой вопрос, когда проводил некоторые исследования для regex bounty quest .)

Также существующее решение проверяет, что запятая не сопровождается круглыми скобками, но это не гарантирует, что этов скобках.

Регулярное выражение очень просто:

\(.*?\)|(,)

Левая часть чередования соответствует полному набору скобок.Мы будем игнорировать эти матчи.Правая сторона сопоставляет и вводит запятые в Группу 1, и мы знаем, что они являются правыми запятыми, потому что они не совпадают с выражением слева.

В этом demo вы можете видетьГруппа 1 захватывает в нижней правой панели.

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

Чтобы сопоставить запятые, вынеобходимо осмотреть группу 1. Единственная цель этой полноценной программы в жизни - сделать именно это.

import java.util.*;
import java.io.*;
import java.util.regex.*;
import java.util.List;

class Program {
public static void main (String[] args) throws java.lang.Exception  {

String subject = "12,44,foo,bar,(23,45,200),6";
Pattern regex = Pattern.compile("\\(.*?\\)|(,)");
Matcher regexMatcher = regex.matcher(subject);
List<String> group1Caps = new ArrayList<String>();

// put Group 1 captures in a list
while (regexMatcher.find()) {
if(regexMatcher.group(1) != null) {
group1Caps.add(regexMatcher.group(1));
}
} // end of building the list

// What are all the matches?
System.out.println("\n" + "*** Matches ***");
if(group1Caps.size()>0) {
for (String match : group1Caps) System.out.println(match);
}
} // end main
} // end Program

Вот демоверсия live

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

Ссылка

  1. Как сопоставить шаблон, кроме как в ситуациях s1, s2, s3
  2. Какчтобы соответствовать шаблону, если ...
1 голос
/ 07 марта 2019

регулярное выражение с использованием Negative Look-forward

,(?![^(]*\))
0 голосов
/ 27 января 2012

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

String beforeParen = longString.substring(longString.indexOf('(')) + longString.substring(longString.indexOf(')') + 1);
int firstComma = beforeParen.indexOf(',');
while (firstComma != -1) {
    /* do something. */
    firstComma = beforeParen.indexOf(',', firstComma + 1);
}

(Конечно, это предполагает, что всегда есть ровно одна открывающая скобка и одна совпадающая закрывающая скобка, приходящая через некоторое время после нее.)

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