Регулярное выражение Java для простых пар ключ-значение с суффиксом

Рассмотрим набор строк, подобных следующему:

Memory size = 4,194,304 KB
Cache size=   32,768 K
Number of cores = 8
Note   =4,000,000 KB is less than 4 GB

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

"Memory size", "4,194,304", "KB"
"Cache size", "32,768", "K"
"Number of cores", "8"
"Note", "4,000,000 KB is less than 4 GB"

Это группы key, value и (необязательно) suffix.

Дополнительные требования:

  • Значение (то есть часть после '=') не обязательно является числом
  • Любые пробелы по обе стороны от «:» должны быть удалены за один проход без возврата.
  • Сопоставление строк «KB» и ​​«K» не чувствительно к регистру.
  • Захваченные группы всегда должны иметь один и тот же индекс (в идеале 3 группы для ключа/значения/суффикса с одинаковым индексом группы для всех совпадений).

Ясно, что простое выражение типа

  • ([^=]+) *: *([^=]+)

не полностью покрывает приведенную выше спецификацию.


person PNS    schedule 28.01.2013    source источник


Ответы (3)


Регулярное выражение, полностью покрывающее указанную выше спецификацию:

^([^=]+?) *= *(.+?) *$

ИЗМЕНИТЬ

Оказывается, я пропустил часть K/KB. Вот исправленная версия:

^([^=]+?) *= *(.+?) *(KB?)? *$
person Carlo Pellegrini    schedule 28.01.2013
comment
Это соответствует всем строкам, но не создает отдельную группу для KB или K. +1 за помощь. - person PNS; 28.01.2013
comment
@PNS Упс... Я изменил ответ. Теперь он должен работать как просили - person Carlo Pellegrini; 28.01.2013
comment
Это работает, и на самом деле он фиксирует ответы всего в 3 группах, всегда с одним и тем же индексом. Хороший! :-) - person PNS; 28.01.2013
comment
Что касается нечувствительности к регистру, вы также можете написать: ^([^=]+?) *= *(.+?) *([Kk][Bb]?)? *$ - person Carlo Pellegrini; 28.01.2013
comment
Чтобы сделать шаблон нечувствительным к регистру, вы можете использовать метод компиляции с флагом Pattern.CASE_INSENSITIVE, например Pattern.compile("regex",Pattern.CASE_INSENSITIVE);, или просто запустить регулярное выражение с (?i), например (?i)^([^=]+?) *= *(.+?) *(KB?)? *$. - person Pshemo; 28.01.2013
comment
Спасибо за это. В этом случае может быть немного быстрее сделать это явно. Следует также отметить, что для удаления всех пробелов (а не только символа ПРОБЕЛ) следует использовать \s. - person PNS; 28.01.2013

Что-то вроде этого должно работать:

^(.*?)\s*=\s*(?:([\d,]+)\s*(K|KB)$|(.*))

^ - соответствует началу строки

(.*?) захватить левый термин, сопоставив что-либо (? делает его нежадным, иначе он съест все пробелы).

\s*=\s* соответствует и отбрасывает знак равенства и все пробелы вокруг него.

(?:([\d,]+)\s*(K|KB)$|(.*)) Эта длинная группа соответствует либо тому, либо другому. (?: делает группу незахватываемой, потому что вы не хотите записывать все целиком.

([\d,]+)\s*(K|KB)$ если есть число, за которым следует только K или KB и конец строки, сопоставьте это в двух группах.

(.*) в противном случае сопоставить все, что осталось, в одну группу.

person Community    schedule 28.01.2013
comment
Это работает, но не фиксирует значение в одном и том же групповом индексе все время. Он создает 4 группы вместо 3, а ответ для строк 3 и 4 находится в группе 4 вместо группы 2. - person PNS; 28.01.2013

попробуйте и скажите мне, если это сработало:

(.*) *= *(.*) (.*)
person Edgard Leal    schedule 28.01.2013
comment
Это не так, но +1 за помощь. - person PNS; 28.01.2013
comment
Это не близко. (.*) всегда будет занимать все пробелы, поэтому ваш `*` никогда не будет соответствовать чему-либо. После знака равенства вы сопоставляете один символ с одной группой, затем все остальное со второй группой. - person ; 28.01.2013
comment
Отредактированная версия лучше, но она по-прежнему не работает (например, она фиксирует ГБ в 4-й строке как отдельный ответ. Вы можете протестировать ее на regexplanet.com/advanced/java/index.html и убедитесь в этом. - person PNS; 28.01.2013