Разбор сложной строки с помощью регулярных выражений - PullRequest
0 голосов
/ 15 июня 2010

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

Возьмите следующую строку

"+ ПОЛЬЗОВАТЕЛЬ = Боб Смит-ГРУП = Администратор + ФУНКЦИЯ = Чтение / ФУНКЦИЯ = Запись"

Ранее для моего регулярного выражения у меня было следующее: [+ \\ - /]

Что бы превратить результат в

ПОЛЬЗОВАТЕЛЬ = Боб Смит
GROUP = Администратор
FUNCTION = Чтение
FUNCTION = Запись
FUNCTION = Читать

Но теперь у меня есть значения с черточками в них, что приводит к неправильному выводу

Новая строка выглядит как "+ USER = Bob Smith-GROUP = Admin + FUNCTION = Чтение / FUNCTION = Запись / FUNCTION = Чтение-запись"

Что дает мне следующий результат и нарушает структуру ключ = значение.

ПОЛЬЗОВАТЕЛЬ = Боб Смит
GROUP = Администратор
FUNCTION = Чтение
FUNCTION = Запись
FUNCTION = Читать
Напишите

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

Ответы [ 4 ]

0 голосов
/ 16 июня 2010

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

Предположим, вы получили строку вроде:

one=a-two=b-three=c-d-four=e

Должно ли это анализироваться?

one=a
two=b
three=c-d
four=e

Или это должно разобраться в этом?

one=a
two=b
three=c
d-four=e

Откуда ты знаешь?На чем основано ваше решение?

0 голосов
/ 15 июня 2010

На основе вашего второго примера это регулярное выражение: (\w+)=([\w|-|\s]+) возвращает эти результаты:

USER=Bob Smith
GROUP=Admin
FUNCTION=Read
FUNCTION=Write
FUNCTION=Read-Write

В скобках указаны группировки для каждого элемента, поэтому каждое совпадение будет содержать две группы, первая будет иметь часть перед = (так USER, GROUP, FUNCTION), а вторая будет иметь значение (Bob Smith, Admin, Read , Запись, чтение-запись)

Вы также можете назвать группы, если это облегчит задачу:

(?<funcrion>\w+)=(?<value>[\w|-|\s]+)  

Или, если вы не заботитесь о группах, вы можете полностью удалить паренсы

\w+=[\w|-|\s]+
0 голосов
/ 15 июня 2010

Другой вариант, если у вас ограниченный набор ключей, вы можете просто сопоставить:

(?<=[+-\\/])(USER|GROUP|FUNCTION)=[^=]+(?=$|[+-\\/](?:USER|GROUP|FUNCTION))

Что в Java я, вероятно, реализовал бы следующим образом:

String Key = "USER|GROUP|FUNCTION" ;
String Delim = "[+-\\/]";
Pattern p = Pattern.compile("(?<="+Delim+")("+Key+")=[^=]+(?=$|"+Delim+"(?:"+Key+"))");

Это зависит от того, например, что «Запись» не является допустимым ключом (и если вы можете принудительно использовать регистр ключейбыть "написать" или "ЗАПИСАТЬ", значит, это будет работать).

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

Matcher m = p.Matcher( InputText );
StringBuffer Result = new StringBuffer("");

while ( m.find() )
{
   Result.append( m.Group() + "\n" );
}
0 голосов
/ 15 июня 2010

Вы не указали, какой движок регулярных выражений вы используете, но это работает, если у вас есть lookahead / lookbehind.

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

(?<=[+-\/])[A-Z]+=(?:(?![A-Z]+=)[^=])+(?=[+-\/]|$)


И вот моя попытка объяснить это (не уверен, насколько это имеет смысл):

(?x)         # enable regex comment mode
(?<=[+-\/])  # start with one of the delimiters, but excluded from match
[A-Z]+       # match one or more uppercase (for the key)
=            # match the equal sign

(?:          # start non-capturing group

  (?!          # start negative lookahead, to prevent keys matching
    [A-Z]+=      # a key and equals (since in negative lookahead, this is what we exclude)
  )            # end the negative lookahead
  [^=]         # match a character that's not =

)+           # end non-capturing group, match one or more times, until...

(?=[+-\/]|$) # next char must be delimiter or end of line for match to succeed

1011 *
*

Для Java string-> regex обратные косые черты необходимо экранировать (как в кавычках, если они есть):

Pattern p = Pattern.compile("(?<=[+-\\/])[A-Z]+=(?:(?![A-Z]+=)[^=])+(?=[+-\\/]|$)");


И если требуются группы захвата, просто добавьте скобки вокруг соответствующих частей:

Pattern p = Pattern.compile("(?<=[+-\\/])([A-Z]+)=((?:(?![A-Z]+=)[^=])+(?=[+-\\/]|$))");


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

Matcher m = p.Matcher( InputText );
StringBuffer Result = new StringBuffer("");

while ( m.find() )
{
   Result.append( m.Group() + "\n" );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...