Регулярное выражение для сопоставления всего, кроме определенных разделителей - PullRequest
1 голос
/ 05 марта 2009

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

джон | COL-DELIM | Самка | COL-DELIM | 55 | ROW-DELIM | джордж | COL-DELIM | Jetson | COL-DELIM | 90 | ROW-DELIM |

Я хочу сделать две вещи:

1) Убедитесь, что строка "выглядит" правильно (то есть соответствует ли она регулярному выражению)

2) Вытащите каждую «строку», затем сможете разобрать каждую строку

Значения между разделителями (| COL-DELIM | и | ROW-DELIM |) могут быть любыми (не только строками, числами и т. Д.).

(() (\ |. COL-DELIM \ |) () (\ |. COL-DELIM \ |) (*) (\ |. ROW-DELIM \ |)) +

Естественно, это не работает в / с (. *) Вещей ... какие-либо предложения?

Ответы [ 2 ]

6 голосов
/ 05 марта 2009

Люди, похоже, не понимают, что им не нужно использовать RE (или SQL, но это другая проблема :-) для каждой задачи, особенно с процедурным кодом, чище.

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

Я бы просто обработал строку, токен за токеном, где токен является одним из:

  • не разделитель.
  • разделитель столбцов.
  • разделитель строк.

Начните с пустого списка столбцов, затем извлеките (используя indexOf / substring) до первого следующего разделителя строки / столбца, добавив этот текст в список столбцов.

Если разделителем является столбец, продолжайте.

Если разделителем является строка, проверьте количество столбцов и обработайте список, как требуется.

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

Извините, если вы действительно использовали метод RE, но я не верю, что он необходим (или даже желателен) здесь.

Псевдокод (только первый срез, может быть слегка ошибочным):

def processStr(s):
    if not s.endsWith ("|ROW-DELIM|"):
        error "Invalid format"
    columnList = []
    while not s.equals (""):
        nextRowDelim = s.indexOf ("|ROW-DELIM|")
        nextColDelim = s.indexOf ("|COL-DELIM|")
        if nextColDelim == NotFound:
            nextColDelim = nextRowDelim + 1
        nextDelim = minimumOf (nextRowDelim,nextColDelim)

        columnList.add (s.substring (0, nextDelim))
        s = s.substring (nextDelim)

        if nextDelim == nextRowDelim:
            s = s.substring (length ("|ROW-DELIM|"))
            processColumns (columnList)
            columnList = []
        else:
            s = s.substring (length ("|COL-DELIM|"))

Вы можете легко добавить код для проверки правильного количества столбцов в этом коде или в processColumns(), если вы этого хотите.

3 голосов
/ 05 марта 2009

Вам не нужно использовать ".*", чтобы соответствовать «чему-либо». Фактически, в большинстве случаев, ".*" не так.

Если ваш двоеточие было одним символом (скажем, ";"), вы можете использовать это для соответствия столбцу:

[^;]*                      // "anything that's *not* a semi-colon"
([^;]*);([^;]*);([^;]*)\n  // three columns, ending with \n

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

Если "|COL-DELIM|" и "|ROW-DELIM|" действительно являются фиксированными последовательностями символов, я предлагаю вам split() строку на них, а не полагаться на регулярное выражение.

  • разделить на "|ROW-DELIM|", чтобы получить массив "строк" строк
  • разделить каждую строку - строку на "|COL-DELIM|", чтобы получить массив столбцов
  • проверьте длину массива, чтобы убедиться, что у вас есть правильное количество столбцов
  • итерация массива столбцов для обработки данных.

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

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