Как мне разобрать повторяющийся шаблон с регулярным выражением - PullRequest
3 голосов
/ 27 сентября 2010

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

Регулярное выражение: @ISNULL\('(.*?)','(.*?)','(.*?)'\)
Строка: @ISNULL('1','2','3')
Результат:

Group[0] "@ISNULL('1','2','3')" at 0 - 20 
Group[1] "1" at 9 - 10 
Group[2] "2" at 13 - 14  
Group[3] "3" at 17 - 18  

Отлично работает.Проблема начинается, когда мне нужно найти неизвестное количество аргументов (2 и более).

Какие изменения мне нужно внести в регулярное выражение, чтобы найти все аргументы, которые будут встречаться в строке?

Итак, если я проанализирую эту строку "@ISNULL('1','2','3','4','5','6')" Я найду все аргументы.

Ответы [ 2 ]

2 голосов
/ 27 сентября 2010

Если вы не знаете количество потенциальных совпадений в повторяющейся конструкции, вам нужен механизм регулярных выражений, который поддерживает захват в дополнение к группам захвата. В настоящее время только .NET и Perl 6 предлагают это.

В C #:

  string pattern = @"@ISNULL\(('([^']*)',?)+\)";
  string input = @"@ISNULL('1','2','3','4','5','6')";
  Match match = Regex.Match(input, pattern);
  if (match.Success) {
     Console.WriteLine("Matched text: {0}", match.Value);
     for (int ctr = 1; ctr < match.Groups.Count; ctr++) {
        Console.WriteLine("   Group {0}:  {1}", ctr, match.Groups[ctr].Value);
        int captureCtr = 0;
        foreach (Capture capture in match.Groups[ctr].Captures) {
           Console.WriteLine("      Capture {0}: {1}", 
                             captureCtr, capture.Value);
           captureCtr++; 
        }
     }
  }   

В других вариантах regex вы должны сделать это в два этапа. Например, на Java (фрагмент кода предоставлен RegexBuddy ):

Сначала найдите нужную вам строку:

Pattern regex = Pattern.compile("@ISNULL\\(('([^']*)',?)+\\)");
// or, using non-capturing groups: 
// Pattern regex = Pattern.compile("@ISNULL\\((?:'(?:[^']*)',?)+\\)");
Matcher regexMatcher = regex.matcher(subjectString);
if (regexMatcher.find()) {
    ResultString = regexMatcher.group();
} 

Затем используйте другое регулярное выражение для поиска и повторения ваших совпадений:

List<String> matchList = new ArrayList<String>();
try {
    Pattern regex = Pattern.compile("'([^']*)'");
    Matcher regexMatcher = regex.matcher(ResultString);
    while (regexMatcher.find()) {
        matchList.add(regexMatcher.group(1));
    } 
0 голосов
/ 27 сентября 2010

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

'(\d)+?'

Это просто класс \d и удаленный посторонний материал @ISNULL, так как я предполагаю, что вас интересуют только сами параметры. Вам может не понадобиться + и, конечно, я не знаю, поддерживает ли используемый вами движок ленивый оператор ?, просто попробуйте.

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