2015-09-30 2 views
0

Из следующих данных .xxx[val1, val2, val3] необходимо извлечь значения val1, val2 и val3.Извлечение нескольких экземпляров текста переменной длины без нескольких шаблонов

Если использовать этот шаблон @"\[(.*?), (.*?), (.*?)\]", данные могут быть извлечены, но при изменении строки данных он не сможет получить все данных.

Возьмите эти переменные примеры

.xxx[val1] или .xxx[val1, val2, val3, val4, val5] или, наконец, .xxx[{1-N},].

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

+1

Если вы не можете определить шаблоны, то вы будете в затруднении, чтобы создать подходящий регулярное выражение, чтобы соответствовать им. Много земли покрывается «струна может варьироваться». – HABO

+1

Ausgezeichnet вопрос фактически. Я переформулировал это для англоязычной аудитории, но мне было ясно, о чем вы спрашиваете. – OmegaMan

+0

Спасибо большое :) –

ответ

3

Что было бы правильным образцом для этого?

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

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

Строка может варьироваться.

Оказывается своим примером, что если бы мы должны были думать, как компилятор, маркеры разделяются либо , или окончание ]. Итак, давайте разберемся с этим знанием (известными).

Лучший способ захвата - использовать до тех пор, пока не будет найдено известное. Использование не набор [^ ] образец лучше всего; который говорит совпадение персонажа не в этом наборе. Затем добавьте наш общий квантификатор +, который говорит один или несколько. Эффективно заменив .* на ваш старый рисунок, но в обратном.


var data = ".xxx[val1, val2, val3, val4, val5]"; 

var pattern = @" 
[^[]+      # Consume anything that is *not* a brace 
          # but don't match it , (.xxx is the first anchor) 
\[      # Starting brace consumed 
(      # Start of match captures 
    (?<Token>[^\s,\]]+) # Named Match grouping called `Token` where one or more 
          # of anything not a space, comma or end brace is captured. 
    [\s,\]]+    # Consume the token's `,` or space or final bracket. 
)+      # End match captures, one or more 
]       # Ending brace." 
; 

// IgnorePatternWhitespace allows us to comment the pattern, 
// does not affect parser processing. 

Regex.Match(data, pattern, RegexOptions.IgnorePatternWhitespace) 
    .Groups["Token"] 
    .Captures 
    .OfType<Capture>() 
    .Select(cp => cp.Value); 

Результат

enter image description here

+0

Вау! Спасибо за этот ответ :) –

1

Простой способ сделать это, просто совпадение со всем внутри [], а затем разбить матч.

text.match(/\[(.*)\]/)[1].split(", "); //And now you have an array with var1,var2..etc 

Вот пример Javascript, я не делаю C#, так что не хочу портить его вверх :)

2

Вы могли бы захватить @"\[(.*?)\]" на первом этапе, а затем разделить на ,, который будет конечно, намного быстрее, чем использование регулярного выражения, чтобы сделать то же самое.

1

Несмотря на то, что группа перезаписывает ее значение, если она повторяется, она хранит весь стек захватов в виде коллекции захвата, возвращаемой каждой группой в Group.Captures Property.

Group.Captures Property

Реальная полезность имущества Захватывает происходит, когда квантор применяется к группе захвата, так что группа захватывает несколько подстрок в одном регулярном выражении. В этом случае объект Group содержит информацию о последней захваченной подстроке, тогда как свойство Captures содержит информацию обо всех подстроках, захваченных группой.

Затем, вы можете просто использовать этот шаблон:

\[(?:([^,\]]+),?\s*)+\] 

Код:

string pattern = @"\[(?:([^,\]]+),?\s*)+\]"; 
var re = new Regex(pattern); 
var text = @".xxx[val1, val2, val3]"; 


MatchCollection matches = re.Matches(text); 
for (int mnum = 0; mnum < matches.Count; mnum++) 
{ //loop matches 
    Match match = matches[mnum]; 
    Console.WriteLine("Match #{0} - Value: {1}", mnum + 1, match.Value); 
    int captureCtr = 0; 
    foreach (Capture capture in match.Groups[1].Captures) 
    { //loop captures for the 1st Group 
     Console.WriteLine("  Capture {0}: {1}", 
         captureCtr, capture.Value); 
     captureCtr += 1;     
    } 
} 

Выход:

Match #1 - Value: [val1, val2, val3] 
     Capture 0: val1 
     Capture 1: val2 
     Capture 2: val3