2013-07-01 1 views
3

Я хотел бы создать регулярное выражение, которое соответствует непревзойденным прямоугольным скобкам. Примеры:Отрицательный lookbehind и квадратные скобки

]ichael ==> match ]

[my name is Michael] ==> no match

Нет гнездовые пары квадратных скобок происходит в моем тексте.

Я попытался использовать отрицательный lookbehind для этого, более конкретно я использую это регулярное выражение: (?<!\[(.)+)\], но, похоже, это не трюк.

Любые предложения?

+1

который regex аромат вы используете? –

+0

Я пытаюсь проверить RegExr, но я не знаю, какой движок он использует. Я буду применять его либо с Java, либо с Python –

+1

Это использует аромат ECMAScript, реализованный ActionScript. Лучше используйте тестер, который использует аромат, который вы, в конце концов, будете использовать, например http://www.regexplanet.com/ –

ответ

3

Если вы не используете .NET, lookbehind должны иметь фиксированную длину. Так как вы просто хотите, чтобы обнаружить, есть ли какая-либо несогласованные закрывающие скобки, вы на самом деле не нужен, хотя назад ':

^[^\[\]]*(?:\[[^\[\]]*\][^\[\]]*)*\] 

Если это соответствует у вас есть непревзойденная закрывающая скобка.

Это немного легче понять, если вы понимаете, что [^\[\]] является инвертированный символьный класс, который соответствует ничего, кроме квадратных скобок, и если вы положите его в freespacing режиме:

^    # start from the beginning of the string 
[^\[\]]*  # match non-bracket characters 
(?:   # this group matches matched brackets and what follows them 
    \[   # match [ 
    [^\[\]]*  # match non-bracket characters 
    \]   # match ] 
    [^\[\]]*  # match non-bracket characters 
)*    # repeat 0 or more times 
\]    # match ] 

Так что пытается найти a ] после сопоставления 0 или более совпадающих пар скобок.

Обратите внимание, что часть между ^ и ] функционально эквивалентна решению Тима Пицкера (что, по-моему, немного понятнее концептуально). То, что я сделал, - это метод оптимизации, называемый "unrolling the loop". Если ваш аромат обеспечивает притяжательные квантификаторы, вы можете превратить все * в *+, чтобы повысить эффективность еще больше.


О вашей попытке

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

[abc]def] 

Так как первый и второй ] имеют [ где-то перед ними. Если вы используете .NET, самое простое решение

(?<!\[[^\[\]]*)\] 

Здесь мы используем без скобок символы в повторении, так что мы не смотрим мимо первого [ или ] мы встречаем слева.

+1

Имейте в виду, что если вы закончите использовать Java, вам придется избегать * всех * литеральных скобок: '[^ \ [\]] * \]'. Тогда вам придется избегать экранов, когда вы пишете его как строковый литерал Java: '" [^ \\ [\\]] * \\] "'. –

+0

@AlanMoore спасибо. Я не знал, что Java не допускает однозначно невыпадающих скобок. –

+0

Он автоматически выходит из закрывающей скобки, если это первый символ, указанный (например, '[]]', '[^]]'). Я вообще избегаю этого; хит удобочитаемости дополнительных символов более чем компенсируется повышенной визуальной симметрией. Это облегчает перенос регулярного выражения в другие вкусы. –

2

Вам не нужно lookaround на всех (и было бы трудно использовать большинство языков не позволяют неограниченной длиной утверждения 'назад):

((?:\[[^\[\]]*]|[^\[\]]*)*+)\] 

будет соответствовать любому тексту, который заканчивается в закрытии если перед ним нет соответствующего открывающего кронштейна. Это не (и по вашему вопросу не нужно) обрабатывать вложенные скобки.

Часть до ] находится в $1, так что вы можете повторно использовать ее позже.

Объяснение:

(   # Match and capture in group number 1: 
(?:  # the following regex (start of non-capturing group): 
    \[  # Either a [ 
    [^\[\]]* # followed by non-brackets 
    \]  # followed by ] 
|   # or 
    [^\[\]]* # Any number of non-bracket characters 
)*+  # repeat as needed, match possessively to avoid backtracking 
)   # End of capturing group 
\]   # Match ] 
+0

@ m.buettner: Да, я это тоже заметил :) –

+0

Привет, Тим. Ну, возможно, [RegExr] (http://gskinner.com/RegExr/) не лучшее место для тестирования, но ваше регулярное выражение захватывает текст, который также включен в квадратные скобки. И как насчет того, хочу ли я только захватить правую скобку, а не текст? –

+0

@YannisP .: Он должен соответствовать этому, иначе он не знал, будет ли следующий '' 'единым или нет. Что касается вашего второго вопроса, это зависит от вашего двигателя регулярных выражений (m.buettner попросил эту информацию некоторое время назад, помните?). –

-1
\](.*) 

будет соответствовать на все после ]:

]ichael -> ichael 
[my name is Michael] -> 
+0

Но это ничего не говорит о том, имеет ли эта закрывающая скоба соответствующая открывающая скоба. –

+0

Это не ответит на вопрос –

+0

Добро пожаловать в [so]! Ненавижу, чтобы понизить рейтинг совершенно нового пользователя, но это даже не близко. Вы вернете очки, если вы удалите ответ. –

0

Это следует сделать это:

'^[^\[]*\]' 

В основном говорит выбор любой закрывающей квадратной скобки, которая не имеет открытой квадратной скобки между ней и началом линии.

+0

Спасибо Дэйв. Как я могу просто совместить правые ']' на строке? –

+0

Не уверен, что вы пытаетесь сделать, но вы можете использовать это '(? <=^[^ \ [] *) \]', Который использует внешний вид. Но какова точка соответствия квадратной скобки, когда вы знаете, что это квадратная скобка? –

+0

@DaveSexton, то у вас есть отрицательный lookbehind переменной длины снова. –