2014-09-12 4 views
1

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

foo :6 

на две группы: Текст и номер. Группа номеров должна заполняться только в том случае, если символ «:» предшествует самому числу.

так:

foo 6 -> Text = "foo 6" 
foo :6 -> Text = "foo", Number = "6" 

Лучшее, что я мог придумать до сих пор

(?<Text>.+)(?=:(?<Number>\d+)h?)? 

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

Любые предложения?

+0

(= :( \ D +?) Ч)? – vks

+0

Почему бы просто не использовать split? – Donal

ответ

2

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

Ниже регулярное выражение будет захватывать все символы в имени группа Text за исключением :\d+ (то есть :, за которым следует одно или несколько номеров). Если он находит двоеточие чисел, то он начинает захватывать номер в имени группы Number

^(?<Text>(?:(?!:\d+).)+(?=$|\s+:(?<Number>\d+)$)) 

DEMO

String input = "foo 6"; 
String input1 = "foo :6"; 
Regex rgx = new Regex(@"^(?<Text>(?:(?!:\d+).)+(?=$|\s+:(?<Number>\d+)$))"); 

foreach (Match m in rgx.Matches(input)) 
{ 
Console.WriteLine(m.Groups["Text"].Value); 
} 
foreach (Match m in rgx.Matches(input1)) 
{ 
Console.WriteLine(m.Groups["Text"].Value); 
Console.WriteLine(m.Groups["Number"].Value); 
} 

Выход:

foo 6 
foo 
6 

IDEONE

+0

@Unihedron обновлен .. –

+0

Кажется, лучший матч для того, что я хочу сделать. Благодарю. – Chris

0

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

"foo :6".Split(':'); 
5

Если вы действительно хотите использовать регулярное выражение, вы можете написать довольно простой, без lookarounds:

(?<Text>[^:]+):?(?<Number>\d*) 

На мой взгляд, регулярные выражения должны быть как можно более простым; если вам не нужны пробелы вокруг группы Text, я предлагаю вам использовать match.Groups["Text"].Value.Strip().

Обратите внимание, что если вы разбираете многострочную строку, этот шаблон не будет работать, потому что, как указано ниже, @OscarHermosilla, [?:]+ также будет соответствовать символам новой строки. Исправление просто, хотя, изменить его с [^:\n]

+0

@Unihedron Я думаю, это зависит от намерений OP – BlackBear

+0

См. Тестовый пример: 'foo: 6 -> Text =" foo ", Number =" 6 "' – Unihedron

+0

Я согласен с тобой, регулярное выражение должно быть простым, и это выполнит эту работу. Но он должен применяться индивидуально для каждой строки, подлежащей анализу. Но он не будет работать в тексте с несколькими строками, потому что [^:] + также будет соответствовать новой строке. –

0

Вы можете попробовать, как:

(\D+)(?:\:(\d+)) 

или сделать Regex.Split используя этот шаблон:

(\s*\:\s*) 
1

Вы можете повторить текст названия группы чередование.Таким образом:

(?<Text>.+)\s+:(?<Number>\d)|(?<Text>.+) 

DEMO

Основываясь на идее, за этот пост: (?.? +) Regex Pattern to Match, Excluding when.../Except between

+0

Его можно было бы легко исправить, если это необходимо –

+1

Например: '(? . +) \ S + :(? \ d) | (? . +)' –

+0

@Unihedron Не очень , по крайней мере, я попробовал, и он, похоже, не работает http://regex101.com/r/vJ4hI8/1 –

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