2013-08-23 4 views
0

У меня есть file с чем-то вродеPerl соответствие слишком нежадным регулярное выражение случай

<post href="http://example.com/" description="Example website" tag="more text"/> 

То, что я хочу, чтобы это Example website. Выполнение:

cat file | perl -pe 's/.*description=".*?"//' 

работает, как ожидалось, и я получаю tag="more text"/>, но при попытке:

cat file | perl -pe 's/.*description="(.*)?"/\1/' 

я Example website" tag="more text/>, в то время как я ожидал получить Example website. Таким образом, кажется, что есть что-то с захватом и обратной ссылкой, которая не работает должным образом, и хотя я думаю, что могу понять, почему, я не уверен, как ее решить.

Я всегда мог сделать:

cat file | perl -pe 's/.*description="//;s/".*//' 

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

+0

** Не используйте регулярные выражения для анализа HTML. Используйте подходящий модуль синтаксического анализа HTML. ** Вы не можете надежно проанализировать HTML с регулярными выражениями, и вы столкнетесь с печалью и разочарованием в будущем. Как только HTML изменится с ваших ожиданий, ваш код будет сломан. См. Http://htmlparsing.com/perl для примеров того, как правильно анализировать HTML с помощью модулей Perl, которые уже были написаны, протестированы и отлажены. –

+0

Я знаю, что я не должен пытаться анализировать HTML с помощью регулярных выражений, но это XML-код, полученный в ответ от вызова API, поэтому он не отклоняется, поскольку он уже содержит только то, что меня интересует. Если API ответ всегда меняется, так что мой код должен адаптироваться, но в этом случае не будет никаких непредвиденных случаев, которые делают регулярные выражения «опасными» в этом случае. – user137369

ответ

1

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

Изменения:

description="(.*)?" 

к:

description="(.*?)" 

и у вас должны быть ожидаемые результаты.

+0

Я подумал (и попробовал) об этом, и он не работал, теперь я понимаю, почему, я забыл поставить трейлинг '. *', Поэтому он должен быть 'cat file | perl -pe 's /.* description = "(. *?)".*/\ 1/''. Я все равно приму ответ, спасибо. – user137369

+0

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

+0

Да, я знаю, теперь он работает так, как ожидалось. Спасибо. – user137369

1

Метахарактер ? имеет два значения в регулярных выражениях.

Когда он следует за символом, как * или +, который позволяет выражать переменное количество раз, это «нежирный» модификатор.

.*? 
a+? 
(foo){3,}?    # actually, I'm not sure about this one 

это В других контекстах, это означает, что «соответствует 0 или 1 раз»

abc?d     # matches "abcd" or "abd" 

Поставив ? вне группы захвата, вы изменили его ко второму значению. Поместите его в группу захвата, как сказал @smerny.

(.*?) 
Смежные вопросы