Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   Вырезать регуляркой (https://javascript.ru/forum/server/4415-vyrezat-regulyarkojj.html)

greatilya 20.07.2009 11:08

Вырезать регуляркой
 
Помогите написать регулярку. Нужно вырезать из переменной $text все значения ширины типа ' width="ЧЮБОЕ_ЗНАЧЕНИЕ"'. Как я понимаю регуляркой это возможно?

Riim 20.07.2009 11:29

alert(
('dsfsdfds width="ЧЮБОЕ_ЗНАЧЕНИЕ" dsfsd width="5px"fds'
	.match(/ width="[^"]*"/g) || []).join('\n')

);

greatilya 20.07.2009 11:58

Riim,
Спасибо большое! Только мне надо было для PHP. Я модифицировал вот так:
$text = preg_replace("' width=\".*?\"'si", '',$text);

вроде тоже правильно?

Riim 20.07.2009 12:16

Цитата:

Сообщение от greatilya
.*?

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

greatilya 20.07.2009 12:58

Цитата:

Сообщение от Riim
Регулярки с отключением жадности иногда очень тормозят

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

e1f 21.07.2009 13:26

Цитата:

Сообщение от Riim (Сообщение 24802)
Регулярки с отключением жадности иногда очень тормозят.

А можно узнать, почему именно, и чем же так отличается поведение "нежадного" квантификатора?

x-yuri 21.07.2009 16:24

Цитата:

Сообщение от e1f
А можно узнать, почему именно, и чем же так отличается поведение "нежадного" квантификатора?

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

для более сложных задач можно парсить html, для этого есть следующие вещи: http://ua.php.net/manual/en/book.dom.php , http://blog.fedecarg.com/2008/08/07/...-jquery-style/ , или можно просто погуглить на тему "html parser php"

p.s. а зачем понадобилось из строки вырезать ширину? Откуда эта строка берется?

Riim 21.07.2009 16:52

Цитата:

Сообщение от x-yuri
нужно после каждого символа проверять оставшуюся часть шаблона, для жадного это по логике должно произойти один раз, когда найдено наиболее жадное соответствие.

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

e1f 22.07.2009 13:05

Riim,
И все же я не понял принципиальной разницы :( Если квантификатор "жадный", то движок начинает "набирать" на него совпадение, набирает-набирает, пока не упрется, потом идет дальше. Если в процессе он видит, что совпадение невозможно в таком варианте, он "отпускает" один символ от жадного кв-ра и снова топает по проторенному пути.
Если квантификатор "нежадный", то движок хватает первое попавшееся совпадение и радостный топает дальше. Если не может найти совпадение -- возвращается, пробует добавить символ, и потом топать дальше.
Где принципиальная разница?

Riim 23.07.2009 19:59

Цитата:

Сообщение от e1f
Если квантификатор "нежадный", то движок хватает первое попавшееся совпадение и радостный топает дальше

А как ему определить, сколько символов в этом первом попавшемся совпадении?

Вот такая строка: '0123456789012345678901234567890123456789012345678 9012345678901234567890123456789mail@mail.ru'

С жадностью: /[^a-z]*[^0-9]+/

Здесь что бы регулярке сдвинуться на один символ вправо нужно сделать всего одно действие: примерить этот символ к [^a-z]

Без жадности: /[^a-z]*?[^0-9]+/

Что бы сдвинуться на один символ вправо нужно сначала примерить символ к [^0-9] и если не подходит, то тогда уже примерять к [^a-z]. Т. е. два действия. Пока тормозит всего в 2 раза сильней, и теперь заменяем в обоих случаях [^0-9]+ на что-нибудь посложней, вроде того:
RegExp.eMail = '[0-9a-z][.\\-\\w]{20}@(?:[0-9a-z][\\-0-9a-z]*[0-9a-z]\\.)+[a-z]{2,6}';

Регулярка с жадностью сначала вберет в себя все цифры и далее !один! раз примерит RegExp.eMail к 'mail@mail.ru' .
Регулярка без жадности будет примерять RegExp.eMail много-много раз и это примирение уже довольно тяжелое.

зы: если кто-нибудь попросит объяснить сначала, то мне придется сделать себе харакири.

x-yuri 23.07.2009 20:52

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

Riim 23.07.2009 21:40

Цитата:

Сообщение от x-yuri
Так что имхо неочевидно, что быстрее

Если еще немного подумать, то не жадная 100% медленней.

e1f 24.07.2009 15:03

x-yuri, +1

Из вики:
Цитата:

Разница в реализации

При необходимости обработать жадный элемент шаблона, парсер начинает поиск соответствия с конца обрабатываемой строки; при обработке нежадного элемента, проверка производится с текущего места обработки строки до первого несоответствия.
Жадные будут быстрее далеко не всегда. Например, тут:
/a[\w\d]*\d/.test('a1bcdefghjk') -- схватили первое 'a', потом залезли в конец и начали отматывать аж до 'b'. Нежадный схватил бы пустую строку, не нашел за ней цифру, взял 'b' и готово.

Kolyaj 24.07.2009 15:29

Цитата:

Сообщение от e1f
парсер начинает поиск соответствия с конца обрабатываемой строки

Что за бред? Это было бы логично только для .* с модификатором m.

Riim 24.07.2009 16:01

Цитата:

Сообщение от e1f
схватили первое 'a'

Все так.

Цитата:

Сообщение от e1f
потом залезли в конец

Верно.

Цитата:

Сообщение от e1f
начали отматывать аж до 'b'

А вот здесь никуда ничего не отматывается, здесь конец строки не соответствует куску \d и регулярка выдает false.


Цитата:

Сообщение от e1f
Нежадный схватил бы пустую строку, не нашел за ней цифру, взял 'b' и готово.

Здесь сначала берется первое "а", затем \d успешно примеряется к "1" и раз успешно, то куску [\w\d]*? ничего не достается, т. е. соответствие найдено и результат true.

А раз результаты на тестируемом тексте разные, значит сравнивать производительность таким тестом не корректно.

Цитата:

Сообщение от e1f
Из вики:

Кто-то с похмелья туда написал.

e1f 24.07.2009 17:23

Результаты разные? А запускать не пробовали?
>>> /a[\w\d]*\d/.test('a1bcdefghjk')
true
>>> /a[\w\d]*?\d/.test('a1bcdefghjk')
true

В варианте 2 и Вы, и я сказали то же самое :) А вот в варианте 1 именно отматывается
Kolyaj,
Цитата:

парсер начинает поиск соответствия с конца обрабатываемой строки
здесь неточно. имеется в виду с конца максимального совпадения на данном этапе. То есть /a.*b/.test('ab11111111111111111...') отхватит все с b до конца, и только потом начнет обратно ползти

Kolyaj 24.07.2009 17:24

Конец максимального совпадения тоже еще найти надо. Но вы правы в том, что нужно просто знать, где какой квантификатор использовать.

Riim 24.07.2009 18:00

Цитата:

Сообщение от e1f
начнет обратно ползти

И правда, назад еще ползает :blink: .
Ладно, сдаюсь :) .


Часовой пояс GMT +3, время: 12:02.