2013-06-10 4 views
6

В JavaScript, у меня есть строка abcdef и не могу понять это странное поведение:Почему «abcdef» не соответствует (? = Abc) def, но соответствует abc (? = Def)?

  • (?=abc)def оленья кожа соответствовать строке
  • abc(?=def) ли соответствовать строке

Почему?

+0

Возможно, вы хотите вместо этого использовать '(ab: abc) def', который использует не захватывающую группу вместо положительного вида. – DaoWen

+0

@ DaoWen Нет, я уже пробовал это ... try '" abcdef ".replace (/ (?: abc) def /," ")' он заменяет целую строку – Zaffy

ответ

18

В (?=abc)def захват (?=abc) является нулевой шириной и не перемещает курсор вперед в строке ввода после успешного совпадения. Эта конструкция просто говорит, глядя вперед на следующие три символа, чтобы увидеть, являются ли они abc, если они затем проверяют, являются ли эти же символы def. На этом этапе матч терпит неудачу.

Вам нужно понять, как работает двигатель регулярного выражения, чтобы завершить матч. Рассмотрим вашу строку ввода abcdef и ваше регулярное выражение abc(?=def). Двигатель запускается путем сопоставления a, затем перемещает курсор внутри входной строки на следующий символ и пытается сопоставить b, потому что курсор во входной строке находится на b, совпадение получается успешно. Затем движок перемещает курсор внутри входной строки и пытается совместить c и потому, что курсор находится во входной строке на c, совпадение завершается успешно, а курсор во входной строке снова перемещается в следующий символ. Теперь двигатель встречает (?=def), в этот момент двигатель просто смотрит вперед, чтобы увидеть, будут ли следующие три символа, из которых находится курсор во входном скрине, на самом деле def, не перемещая курсор, который они есть, и совпадение завершается успешно.

Теперь рассмотрим строку ввода xyz и регулярное выражение x(?=y)Z. Механизм регулярных выражений помещает курсор в первую букву в строке ввода и проверяет, является ли это x и находит, что x, поэтому он перемещает курсор на следующий символ в строке ввода. Теперь он смотрит вперед, чтобы увидеть, является ли следующий символ y, который он есть, но движок не перемещает введенное текстовое курсорное предисловие, поэтому курсор в тексте ввода остается на y. Затем двигатель смотрит, находится ли курсор на букве z, но поскольку курсор во входном тексте по-прежнему находится на букве y, совпадение не выполняется.

Вы можете прочитать намного больше о положительных и отрицательных lookaheads на http://www.regular-expressions.info/lookaround.html

+0

Все еще havent получил. Если это должно быть «после», попробуйте добавить '^' в начале, результат будет таким же. – Zaffy

+1

Обновлено объяснение, объясняющее, как движок регулярного выражения обрабатывает совпадение совпадения и показывает, что произойдет, если будет выглядеть, когда вставлено в середину выражения примера. Ключ находится в отслеживании того, где курсор находится внутри входного текста. –

+1

удивительный информация! – user1993

2

MDN definition of lookaheads в JavaScript «х»

x(?=y)
соответствует только если «х» следует «у». Это называется взглядом.

Например, /Jack(?=Sprat)/ подходит к «Джеку», только если за ним следует «Справа». /Jack(?=Sprat|Frost)/ соответствует «Джеку», только если за ним следуют «Справа» или «Мороз». Однако ни «Спрат», ни «Мороз» не являются частью результатов матча.

Таким образом, (?=y) предшествует другое утверждение, в данном случае пустая строка, тогда оно будет соответствовать только в том случае, если первый оператор сопровождается вторым.Без ведущего оператора выражение (?="abc") будет совпадать с первыми 3 символами abc без их захвата, а затем снова проверить, будут ли эти символы определены, что не удастся.

4

(?=...) - это взгляд, другими словами, который проверяет строку справа. Также обратите внимание, что lookahead - это утверждение с нулевой шириной, которое не употребляет символ. В вашем первом примере: (?=abc), что означает , следует abc встречи def. Именно по этой причине шаблон терпит неудачу.

В вас втором примере он находит def после abc, то строка соответствует

+1

Очень чисто объясняется утверждение о нулевой ширине, это также объясняет, почему '/ (? = Def) def/.test ('abcdef')' соответствует. –

2

Основа вашего ответа на мой комментарий, я думаю, что вы хотите это positive look-behind:

(?<=abc)def 

Редактировать :

Поскольку вы используете JavaScript (извините, я только прочитал ваш вопрос - я didn ' t посмотреть на теги), почему бы просто не использовать регулярную группу захвата и включить совпадение в шаблоне замены?

"abcdef".replace(/(abc)def/, "$1") 
+0

Несомненно, это будет * classic *, но в javascript нет никаких искажений. – Zaffy

+0

Потому что при замене на '/ g' пропускается замененный текст. Например, '' a1a2a ".replace (/ (a) (\ d) (a)/g," $ 1b $ 2b $ 3 ");' будет 'ab1ba2a' не' ab1bab2ba' – Zaffy

+0

@Zaffy - заменить только внешний вид - * позади * с захватными группами, а не смотреть вперед *, например: '" a1a2a ".replace (/ (a) (\ d) (? = a)/g," $ 1b $ 2b ") // = > "ab1bab2ba" ' – DaoWen

Смежные вопросы