Regex не работает на правильных паренах - PullRequest
0 голосов
/ 08 октября 2008

У меня есть это .NET регулярное выражение:

^(?<prefix>("[^"]*"))\s(?<attrgroup>(\([^\)]*\)))\s(?<suffix>("[^"]*"))$

Правильно соответствует следующим строкам:

"some prefix" ("attribute 1" "value 1") "some suffix"
"some prefix" ("attribute 1" "value 1" "attribute 2" "value 2") "some suffix"

Не удается на ...

"some prefix" ("attribute 1" "value (fail) 1") "some suffix"

... из-за правого парня после «неудачи».

Как я могу изменить свое регулярное выражение так, чтобы группа совпадений attrgroup в конечном итоге содержала "("attribute 1" "value (fail) 1")"? Я смотрю на это слишком долго и мне нужны свежие глаза. Спасибо!

Редактировать: attrgroup никогда не будет содержать ничего, кроме пар строк в двойных кавычках.

Ответы [ 5 ]

2 голосов
/ 08 октября 2008

мое, непроверенное предположение:

^(?<prefix>("[^"]*"))\s(?<attrgroup>(\(("[^"]*")(\s("[^"]*")*)**\)))\s(?<suffix>("[^"]*"))$

настоящим я заменил

[^\)]*

с

("[^"]*")(\s("[^"]*")*)*

Я предположил, что все в скобках либо между двойными кавычками, либо является пробелом.

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

пс. если я прав, то это также проверит группу атрибутов как пары строк в кавычках.

1 голос
/ 08 октября 2008
^(?<prefix>"[^"]*")\s+(?<attrgroup>\(.*\))\s+(?<suffix>"[^"]*")$

исправил это для меня.

Я удалил посторонние неназванные группы и упростил (до «любого символа») группу атрибутов.

A очень стоящих инвестиций - это RegexBuddy от JG Soft

Редактировать: Это не будет проверять группу атрибутов как пары строк в кавычках, но это следует / можно сделать на отдельном шаге регулярного выражения / проверки.

0 голосов
/ 09 октября 2008

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

def parse_String(string):
    index = skip_spaces(string, 0)
    index, prefix = read_prefix(string, index)
    index = skip_spaces(string, index)
    index, attrgroup = read_attrgroup(string, index)
    index = skip_spaces(string, index)
    index, suffix = read_suffix(string, index)
    return prefix, attrgroup, suffix

def read_prefix(string, start_index):
    return read_quoted_string(string, start_index) 

def read_attrgroup(string, start_index):
    end_index, content = read_paren(string, start_index)

    index = skip_spaces(content, 0)
    index, first_entry = read_quoted_string(content, index)
    index = skip_spaces(content, index)
    index, second_entry = read_quoted_string(content, index)
    return end_index, (first_entry, second_entry)


def read_suffix(string, start_index):
    return read_quoted_string(string, start_index)

def read_paren(string, start_index):
    return read_delimited_string(string, start_index, '(', ')')

def read_quoted_string(string, start_index):
    return read_delimited_string(string, start_index, '"', '"')

def read_delimited_string(string, starting_index, start_limiter, end_limiter):
    assert string[starting_index] == start_limiter, (start_limiter 
                                                     +"!=" 
                                                     +string[starting_index])
    current_index = starting_index+1
    content = ""
    while(string[current_index] != end_limiter):
        content += string[current_index]
        current_index += 1

    assert string[current_index] == end_limiter
    return current_index+1, content

def skip_spaces(string, index):
    while string[index] == " ":
        index += 1
    return index

да, это больше кода, и да, по необработанному количеству ключей, это заняло больше времени. Однако, по крайней мере для меня, мое решение гораздо проще проверить. Это увеличивается еще больше, если вы удаляете кучу строк-и-индексов, перемещая все это в класс, который анализирует такие строки в своем конструкторе. Кроме того, легко сделать пропущенный пробел неявным (используя некоторый волшебный метод next-char, который просто пропускает символы до тех пор, пока не появится пробел, если только он не находится в не пропущенном режиме из-за строк. Этот режим можно установить в функция с разделителями, например). Это превратит строку parse_string в:

def parse_string(string):
    prefix = read_prefix()
    attrgroup = read_attr_group()
    suffix = read_suffix()
    return prefix, attrgroup, suffix.

Кроме того, эти функции можно расширить, чтобы охватить более сложные выражения. Произвольно вложенные группы атрибутов? изменение одной строки кода. Вложенные парены? немного больше работы, но нет реальной проблемы.

А теперь, пожалуйста, подожди и опровергни меня за то, что я какой-то еретик-регулярник и какой-то сторонник парсера. >:)

PS: да, этот код не проверен. насколько я знаю, там 3 опечатки, которых я не видел.

0 голосов
/ 08 октября 2008

Не обращаясь к особенностям этого регулярного выражения, я бы порекомендовал использовать инструмент Regex для создания, проверки и проверки правильности регулярных выражений. Для любого нетривиального или выражения, которое вам может понадобиться поддерживать / обновлять, такие инструменты необходимы.

Выезд ...

Regex Coach - Написано на Лиспе, немного старше, но я действительно предпочитаю это другим.

Rad Software Regex Designer - .NET и, возможно, более «современный». Кому-то может понравиться этот.

0 голосов
/ 08 октября 2008

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

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