Как проанализировать файл с парами ключевое слово-значение и {} и разрывы строк в Java? - PullRequest
2 голосов
/ 12 января 2010

В файле у меня есть несколько переменных, которые хранятся так:

author = {Some Author},
link = {some link},
text = { bla bla bla bla bla bla bla bla bla bla bla
bla bla bla bla bla bla bla bla bla bla bla bla bla},
...

Некоторые переменные находятся в многострочном режиме.

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

\\S+\\s*[=][{]\\s*\\S*[},]

Решения, которые работают нормально для меня:

(\w+)\s*=\s*\{(.*?)\}

и

\\S+\\s*[=]\\s*[{].*[},]

Ответы [ 7 ]

6 голосов
/ 12 января 2010

Это не очевидно из вашего поста, но это похоже на файл bibtex. Если это так, то фигурные скобки могут встречаться в фигурных скобках, что означает, что ваш язык не является «регулярным» и не может быть описан с помощью регулярных выражений, таких как то, которое вы предоставляете.

Если нет, то вы хотите что-то вроде

(\w+)\s*=\s*\{(.*?)\}

но написание парсера, наверное, самый респектабельный способ решения вашей проблемы. Если вы анализируете bibtex, менеджер библиографии Java с открытым исходным кодом (например, Jabref) может дать вам некоторые идеи по созданию чего-то более надежного.

4 голосов
/ 12 января 2010

Я бы порекомендовал вам не использовать регулярные выражения для этого, поскольку кажется, что ваш формат слишком свободен. Написание простого синтаксического анализатора, который сначала читает строку до = в качестве ключа, а затем читает внутреннюю часть фигурных скобок до разделительной запятой или конца файла, не заботясь о переводах строки, мне показался бы более простым подходом , И если вам это нужно, вы можете заменить символы новой строки пробелами на ходу. Преимущество также состоит в том, что если ваши значения могут содержать фигурные скобки, соответственно, экранированные, проще обрабатывать их с помощью фактического синтаксического анализатора, чем с регулярными выражениями.

Этот формат кажется достаточно простым и вряд ли будет расширен за счет того, что рукописный синтаксический анализатор вполне подходит. Но для более сложного языка, или даже если вы просто хотите выполнить упражнение, вы можете использовать генератор синтаксического анализатора для создания вашего синтаксического анализатора, который имеет преимущество гораздо более понятного определения языка. Я понимаю, ANTLR является популярным для использования в Java.

1 голос
/ 12 января 2010

Вы можете использовать метод split класса String.

public String[] split(String regex)

Разбивает эту строку вокруг совпадений заданного регулярного выражения.

Вы можете сначала разделить ввод через запятую, а затем разделить текст между {} на пробел (\s).

0 голосов
/ 12 января 2010

Я не уверен, что именно вы спрашиваете, и ваше регулярное выражение не очень помогает в предоставлении дополнительной информации.

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

Примечание: даже ваше последнее регулярное выражение (возможно, следовало бы просто отредактировать ваше сообщение вместо того, чтобы отвечать самому себе: \\S+\\s*[=]\\s*[{].*[},] Делает некоторые вещи, в которых нет необходимости, это, безусловно, испортит вас. Чрезмерное использование [ ] стиль классов персонажей, вероятно, сбивает вас с толку. Ваш последний [},] действительно говорит «сопоставление символов»} или «,», что, я уверен, не совсем то, что вы имеете в виду.

Регекс, похоже, любимый мальчик для битья, но я думаю, что здесь уместно.

Pattern p = Pattern.compile( "\\s*([^={}]+)\\s*=\\s*{([^}]+)},?" );
Matcher m = p.matcher( someString );
while( m.find() ) {
    System.out.println( "name:" + m.group(1) + " value:" + m.group(2) );
}

Регулярное выражение распадается на:

  • Любой предшествующий пробел.
  • Первая группа захвата - это строка ненулевой длины, содержащая только символы, которые НЕ '=', '{' или '}'
  • Любые промежуточные пробелы.
  • '='
  • Любые промежуточные пробелы.
  • '{'
  • Вторая группа захвата - это строка ненулевой длины, содержащая только символы, которые не являются закрывающими '}'
  • '}'
  • Дополнительно ','

Это регулярное выражение должно работать более эффективно, чем версии. *, Потому что ему легче выяснить, где остановиться. Я также думаю, что это понятнее, но я говорю на регулярном языке в разговорной речи. :)

0 голосов
/ 12 января 2010

Использование другого формата файла, вероятно, избавит вас от головной боли, но вы можете разобрать его следующим образом:

Pattern p = Pattern.compile("\\s*(\\w+)\\s*=\\s*\\{(.*?)\\},?\\s*", Pattern.DOTALL);
while (true) {
    Matcher m = p.matcher(input);
    if (!m.find()) break;
    String key = m.group(1);
    String val = m.group(2);
    System.out.println("OK: key=" + key + ", val=" + val);
    input = m.replaceFirst("");
}

Просто замените println на карту.

0 голосов
/ 12 января 2010

Вы должны использовать Свойства , регулярное выражение не является хорошим решением в вашем случае.

0 голосов
/ 12 января 2010

рассматривали ли вы файлы свойств Java? http://en.wikipedia.org/wiki/.properties

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...