2014-02-02 4 views
0

Я пытаюсь понять внешний вид.
Этот пример, который я стараюсь, не работает так, как я ожидал. Я хотел, чтобы попытаться сформировать регулярное выражение, которое будет соответствовать John, но не John.
Следующим:Lookbehind не работает должным образом

$ perl -e ' 
my $var = "John."; 
if($var =~ m/J*/) { 
print "Matches!\n"; 
} 
' 
Matches! 

матчей до и включая . конечно. Проблема заключается в следующем:

$ perl -e ' 
my $var = "John."; 
if($var =~ m/J*(?<![.])/) { 
print "Matches!\n"; 
} 
' 
Matches! 

Для последнего я ожидал, что регулярное выражение будет соответствовать John.потребляя>. < (период)
Затем на следующей позиции он будет выглядеть позади и понимать, что он потреблял период (.) И отклонял матч.
Является ли мое понимание неправильным? Что я здесь испортил?

Update:
Тот же результат и для my $var = "John. ";

Update 2:
Мой вопрос не о том, чтобы соответствовать только John и не John.
Но чтобы понять, как с просмотром назад работает, и если он в этом случае не предполагается работать.

ответ

4

* является оператором количественной оценки, а не заполнителем. Так что A* означает ноль и более A символов. Без какого-либо дополнительного контекста это всегда совпадает, например. "foo" =~ /J*/ - это правда.

То, что вы намеревались написать, было /J.*/, которое делает то, что вы на самом деле описали.

Теперь давайте посмотрим, что происходит, когда мы делаем "John." =~ /(J.*(?<![.]))/:

  • движок регулярных выражений видит J, который соответствует.
  • Следующая картинка .*, которая соответствует ohn..
  • Далее проверено утверждение (?<![.]), которое не выполняется.
  • Regex двигатель поэтому заднийtracks.
  • Повторите попытку .*, но на этот раз только ohn.
  • Далее проверено утверждение (?<![.]), которое преуспевает.

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

$ perl -E'"John." =~ /(J.*(?<![.]))/ and say "<$1>" or say "No match"' 
<John> 

Это часто более эффективно использовать класс символов вместо утверждений и .* количественными , так что мы можем избежать откатов:

/J[^.]*/ 

Однако, это не строго эквивалентно выше регулярных выражений.

+0

+ 1.Отличное объяснение! Большое спасибо – Jim

+1

@Jim: Кстати, '/ (J. * (? nhahtdh

+0

Кроме того, я бы не сказал, что избежать отскока, а скорее уменьшилось. Я бы сказал, что избежать обратного следования при использовании притяжательных кванторов и атомных групп. – Jerry

0

Это регулярное выражение:

/John(?![.])/ 

будет соответствовать John, но не John. Он использует негативный взгляд - впереди утверждение (а не смотреть за).

Если вы хотите совместить полные имена, отличные от «Джона», вам нужно быть более конкретными в отношении того, что вы делаете и не хотите разрешать в матче, так как установка J* будет соответствовать нулю или более J.

Редактировать: Очевидно, я неправильно читал * за сообщение @ amon. Уверен, что смотрится вперед и смотрит.

+0

Но мой вопрос о понимании lookbehind. Не решить проблему не соответствия 'John.' – Jim

+0

отредактирован. Я не думаю, что ты хочешь посмотреть. –

+1

Взгляд сзади перед началом матча. Не ПОСЛЕ. –

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