2010-10-20 1 views

ответ

11

Правильный путь будет:

/([^:]+):(.*)/ 

или

/(.+?):(.*)/ 

Таким образом, вы не соответствие «ничего» слева, вы соответствия «один или больше символов без двоеточия "в первом примере или" совпадение кратчайшей строки любых символов с последующим двоеточием "во втором.

Еще лучший способ НЕ использовать регулярное выражение. Используйте split.

my ($left,$right) = split(/:/, $line, 2); 

The ,2 говорит: "Я хочу, чтобы не более двух полей".

+1

Yap, Энди вправо. '. *' является «жадным», он соответствует как можно большему количеству символов. –

+2

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

+0

Вы правы, @mscha, я добавил два альтернативных способа сделать это. –

2

две проблемы:

  1. было то, что вам нужно закрывающую скобку, ), в конце вашего if заявления
  2. вы хотите не -greedy выражение совпадало количество мере перед тем первая толстая кишка (:)

Попробуйте $line =~ m/(.*?):(.*)/ - обратите внимание на .*? - это означает, что требуется минимум . Обычно .* означает матч максимально возможно.

1

Делать первые .* нежадным также будет работать:

if ($line =~ /(.*?):(.*)/) { 
    print "$1 = $2 " 
} 
1
$line = " TEST: asdas :asd asdasad s"; 

if ($line =~ /(.*?):(.*)/) 
{ 
    print "$1 = $2 " 
} 

Используйте выше вместо этого. Здесь (. *?) Означает нежелательное соответствие. Таким образом, он будет соответствовать, пока не найдет первый ':'

4

Вопрос, как говорят другие, соответствует всем, кроме строки, заканчивающейся greedily(.*). Но то, что они не говорят вам, что когда двигатель регулярного выражения соответствует всем до конца строки, он должен до backtrack, чтобы удовлетворить условию ':'. Поэтому после того, как он проглотил все символы, отличные от строки, он начинает резервное копирование. Как это происходит в обратном направлении, первая найденная толстая кишка является «:» перед «asd». Двоеточие было сопоставлено, оно применяет вторую группу ко всем символам, отличным от строки, которые она удовлетворяет.

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

([^:]+):(.*) 

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

([^:]+):(.*\S) 

Когда он доходит до конца ввода, он откатывается для не-пространства, которое она до сих пор не совпадают. И когда он находит это, он завершает захват.

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

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

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

This post from Regex Guru имеет немного больше об этом.

+0

+1 для отказа от возврата, но это последнее регулярное выражение нуждается в работе. Согласно RegexBuddy, для соответствия тестовой строке OP требуется 48 шагов. Сравните это с '([^:] +): ((?:: S +) +)', который занимает всего 17 шагов. Это не значит, что это вредит вам, это чередование в '(?: \ S | \ S) +', совпадающее с одним или двумя символами на итерацию '+'. –

+0

+1: Нежелательное соответствие будет выполнено, но лучше использовать отрицательный класс символов (например, '[^:]'), когда это возможно. Он не только более эффективен, но и более четко передает ваш смысл будущим программистам. («Мне нужны символы без двоеточия» против «Я хочу любых персонажей, мне все равно, что они»). –

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