(Это продолжение разговора из комментариев к ответу Эвана.)
Вот что происходит, когда применяется ваше (исправленное) регулярное выражение: Во-первых, .+
соответствует всей строке. Затем он отступает, отказываясь от большинства только что совпавших символов, пока не дойдет до точки, где B=
может совпадать. Затем (.+?)
сопоставляет (и фиксирует) все, что видит, пока следующая часть, точка с запятой, не сможет совпасть. Затем последний .+
поглощает оставшиеся символы.
Все, что вас действительно интересует, это "B=" и ";" и что между ними, так зачем сопоставлять остальную часть строки? Единственная причина, по которой вам нужно это сделать, заключается в том, что вы можете заменить всю строку содержимым группы захвата. Но зачем это делать, если вы можете получить прямой доступ к содержимому группы? Вот демонстрация (на Java, потому что я не могу сказать, какой язык вы используете):
String s = "A=abc;B=def_3%^123+-;C=123;";
Pattern p = Pattern.compile("B=(.*?);");
Matcher m = p.matcher(s);
if (m.find())
{
System.out.println(m.group(1));
}
Зачем «заменять», когда «найти» намного проще? Вероятно, потому что ваш API упрощает задачу; поэтому мы делаем это на Java. Java имеет несколько удобных методов, ориентированных на регулярное выражение, в своем классе String: replaceAll()
, replaceFirst()
, split()
и matches()
(который возвращает true
, если регулярное выражение соответствует целой строке), но не find()
. Также нет удобного способа доступа к группам захвата. Мы не можем сравниться с элегантностью однострочников Perl, например:
print $1 if 'A=abc;B=def_3%^123+-;C=123;' =~ /B=(.*?);/;
...поэтому мы довольствуемся такими хаками:
System.out.println("A=abc;B=def_3%^123+-;C=123;"
.replaceFirst(".+B=(.*?);.+", "$1"));
Просто для ясности: я не говорю не использовать эти хаки или что с ответом Эвана что-то не так — это не так. Я просто думаю, что мы должны понимать, почему мы их используем, и на какие компромиссы мы идем при их использовании.
person
Alan Moore
schedule
30.01.2009