2013-03-27 2 views
21

Я хотел бы разбить строку, используя функцию Split в классе Regex. Проблема в том, что он удаляет разделители, и я бы хотел их оставить. Предпочтительно, как отдельные элементы в сплайте.Как сохранить разделители Regex.Split?

Согласно other discussions, который я нашел, есть только неудобные способы достижения этого.

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

+6

Входная строка? ваше регулярное выражение? ожидаемый результат? – I4V

+0

этот '.etc' не дает много информации. о вашем алгоритме, но я могу попробовать хотя бы. См. Мой ответ – I4V

+6

Почему вы так агрессивны? Просто спросите qood вопрос и получите лучший ответ. То, что вы хотите сделать, может быть выполнено даже без 'Regex.Split'. См. [This] (http://www.perlmonks.org/?node=xy+problem) и снова прочитайте мой ответ. – I4V

ответ

59

Просто поместите образец в улавливающей-группу, и матчи будут также включены в результате.

string[] result = Regex.Split("123.456.789", @"(\.)"); 

Результат:

{ "123", ".", "456", ".", "789" } 

Это также работает и для многих других языков:

  • JavaScript: "123.456.789".split(/(\.)/g)
  • Python: re.split(r"(\.)", "123.456.789")
  • Perl: split(/(\.)/g, "123.456.789")

(не Java, хотя)

+0

О, это было даже лучше! Смешной пример - вы соответствуете * любому * на период, который ** фактически ** является периодом. +1 для отличного синтаксиса! Однако по какой-то причине он не улавливает последний элемент, поэтому я получаю только то, что вы сказали, но ** кроме ** для части * 789 *. – 2013-03-27 20:23:03

+0

При чтении смотрите вперед, я читал, что он не включен в результат: Regex.Match («скажем, 25 миль больше», @ «\ d + \ s (? = Миль)»); // OUTPUT: 25 , а в другом заявлении указано, что для включения разделителя при расщеплении оберните шаблон в положительном порядке вперед, например: Regex.Split («oneTwoThree», @ "(? = [A-Z])"); // OUTPUT one Two Three confused – 2016-12-24 19:45:32

+1

@sortednoun При взгляде вперед встречается нулевой символ, только если тело будет соответствовать этой позиции. Ожидаемое тело не является частью матча, поэтому нет ничего лишнего. Текст, согласованный с телом, вместо этого будет включен в следующий элемент массива при расщеплении. '(? = ([A-Z]))' будет создавать дополнительный элемент с буквой И включать его в следующий элемент. –

0

Добавьте их обратно:

string[] Parts = "A,B,C,D,E".Split(','); 
    string[] Parts2 = new string[Parts.Length * 2 - 1]; 
    for (int i = 0; i < Parts.Length; i++) 
    { 
     Parts2[i * 2] = Parts[i]; 
     if (i < Parts.Length - 1) 
      Parts2[i * 2 + 1] = ","; 
    } 
+1

Но это не работает в случае, если регулярное выражение имеет более одного возможного совпадения. – AJMansfield

+1

Что вы будете делать, если не знаете, какой разделитель используется? Можете ли вы повторить пример для нас * Regex * class? – 2013-03-27 19:45:43

6

Использование Matches найти разделителей в строке, а затем получить значения и разделители.

Пример:

string input = "asdf,asdf;asdf.asdf,asdf,asdf"; 

var values = new List<string>(); 
int pos = 0; 
foreach (Match m in Regex.Matches(input, "[,.;]")) { 
    values.Add(input.Substring(pos, m.Index - pos)); 
    values.Add(m.Value); 
    pos = m.Index + m.Length; 
} 
values.Add(input.Substring(pos)); 
+0

О, я понял. Круто. Тем не менее, я бы хотел, чтобы был добавлен дополнительный * Split *, который принимает bool, чтобы решить, следует ли хранить разделители. Думаю, мне придется начинать кодирование. Благодаря! +1 для четкого ответа. – 2013-03-27 20:19:37

3

Говорят, что ввод "abc1defg2hi3jkl" и регулярное выражение, чтобы выбрать из цифр.

String input = "abc1defg2hi3jkl"; 
var parts = Regex.Matches(input, @"\d+|\D+") 
      .Cast<Match>() 
      .Select(m => m.Value) 
      .ToList(); 

части будут: abc1defg2hi3jkl