2015-02-12 3 views
0

Рассмотрим следующую многострочный строку:Извлечение пар ключ-значение из многострочного текста в Java

This is multiline text that needs to be correctly parsed into key-value pairs, excluding all other information. 

Section One: 
    First key = Value One 
    Second key = Value Two 

Section Two: 
    Third key = Value Three 
    Fourth key = Value Four 
    Fifth key = Value Five 

Section Three: 
    Sixth key = Value Six 
    Seventh key = Value Seven 
    Eighth key = Value Eight 

Другими словами, текст состоит из «введения» (некоторые фразы), а затем из нескольких линий, организованных в разделах, каждый из которых имеет «заголовок» (например, Section One) и несколько пар ключ-значение, разделенных =. Ключи могут содержать любой символ, кроме новой строки, и =, и значения могут содержать любой символ, кроме новой строки. Иногда в тексте могут появляться другие нерелевантные строки.

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

Образцы, подобные (?:\r|\n)(\s*[^=\.]+)\s*=\s*(.+), приближаются, но они по-прежнему содержат немного больше требований.

Любые идеи?

+0

Если расстояние является постоянным, а также попробовать '(? <=^{4}) + (= * = * (. *)) ' –

+0

Интервал не постоянный, он не работает. Спасибо хоть. :-) – PNS

ответ

2

Вы почти у цели. Просто измените \s* на <space>*, потому что \s соответствует символу новой строки.

(?:\r|\n) *([^\n=\.]+)(?<=\S) *= *(.+) 

Если он содержит вкладки, а затем изменить space* в выше [ \t]*. (?<=\S) Положительный lookbehind, который утверждает, что совпадению должен предшествовать непространственный символ.

DEMO

String s = "This is multiline text that needs to be correctly parsed into key-value pairs, excluding all other information.\n" + 
     "\n" + 
     " Section One:\n" + 
     " First key = Value One\n" + 
     " Second key = Value Two\n" + 
     "\n" + 
     " Section Two: \n" + 
     " Third key = Value Three\n" + 
     " Fourth key = Value Four\n" + 
     " Fifth key = Value Five\n" + 
     "\n" + 
     " Section Three:\n" + 
     " Sixth key = Value Six\n" + 
     " Seventh key = Value Seven\n" + 
     " Eighth key = Value Eight"; 
Matcher m = Pattern.compile("(?:\\r|\\n)[\\t ]*([^\\n=\\.]+)(?<=\\S)[\\t ]*=[\\t ]*(.+)").matcher(s); 
while(m.find()) 
{ 
    System.out.println("Key : "+m.group(1) + " => Value : " + m.group(2)); 
} 

Выход: (M +).?

Key : First key => Value : Value One 
Key : Second key => Value : Value Two 
Key : Third key => Value : Value Three 
Key : Fourth key => Value : Value Four 
Key : Fifth key => Value : Value Five 
Key : Sixth key => Value : Value Six 
Key : Seventh key => Value : Value Seven 
Key : Eighth key => Value : Value Eight 
+0

Или мы можем использовать \ s * для включения вкладок. – PNS

+0

Вот почему я сказал вам добавить '[\ t] *' –

+0

или https://regex101.com/r/gL0jQ3/2 –