Regex не работает в правильных паренах

У меня есть это регулярное выражение .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"

... из-за правильного символа после слова "fail".

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

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

Согласно вашей входной спецификации, attrgroup когда-либо содержит что-либо, кроме строк в двойных кавычках?

Alex Lyman 08.10.2008 23:10

Хороший вопрос! Ответ - нет, и они всегда идут парами.

Billy Jo 08.10.2008 23:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
189
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

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

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

Стоит инвестировать в очень RegexBuddy от JG Soft.

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

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

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

Проверить...

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

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

Ответ принят как подходящий

моя непроверенная догадка:

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

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

[^\)]*

с

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

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

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

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

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

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.

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

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

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

Другие вопросы по теме