Подтвердить что ты не робот

Почему регулярные выражения жадные по умолчанию?

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

Это только по причинам, связанным с наследством (так было, как это было сделано в первый раз, и каждая реализация копирует это), или есть причина для этого?

4b9b3361

Ответ 1

Истерические Raisens


Часть ответа может включать истоки RE в практических вычислениях. Первоначально они были теоретической концепцией теории автомата и теории формального языка до тех пор, пока Кен Томпсон сам написал реальную реализацию и использовал их в qed и изд (1).

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

Ответ 2

В случае производительности ленивые кванторы не всегда бывают быстрее из-за обратного отслеживания: http://blog.stevenlevithan.com/archives/greedy-lazy-performance

Что касается фактического дизайна, я, честно говоря, не могу сказать, почему кванторы являются жадными по умолчанию, но я задаюсь вопросом, какой контрольный символ использовался бы, чтобы сделать квантификатор жадным, а не ленивым. Я не думаю, что ? сократил бы его: -)

Ответ 4

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

Что касается того, должен ли типичный вариант использования быть неживым, а как насчет следующего: предположим, что у меня есть файл с такими записями, как foo1909, bar3939, baz3331, и я просто хочу извлечь эти числа. Кажется достаточно естественным написать (\ d *) в качестве регулярного выражения для этого.

Можно сказать, что писать так же легко (\ d *)\D или что-то еще, но в основном это всегда так, что программист может быть более явным и менее двусмысленным. Поскольку мы хотели, чтобы поведение по умолчанию было на 100% предсказуемым и тривиальное для вычисления в голове, мне кажется разумным.

Ответ 5

Реальная проблема здесь - оператор замыкания Клейна (звезда); для всего остального в регулярном выражении самое длинное совпадение совпадает с самым коротким совпадением.

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

  • Оба ksh и bash предоставляют формы "longest match" и "shortest match" большинства специальных переменных-изменяющих операторов.

  • Регулярные выражения Lua включают * для самого длинного совпадения закрытия Kleene и - для кратчайшего совпадения закрытия Kleene. Это всегда меня укушает, когда я забываю избежать буквального знака -.

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

Ответ 6

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

Я хочу дать понять, что это неправильно, если только "типичный вариант использования" означает взлом HTML-кода.

Простым примером являются лексические анализаторы для языков программирования. Вы просто не хотите

foo = 42

интерпретируется как 3 переменные, за которым следует знак равенства, за которым следуют 2 числа. Наоборот, обычно вы ожидаете, что ваш синтаксический анализатор рассмотрит максимально возможные совпадения.

До появления HTML, мы, старшие, десятилетиями жили с жадными регулярными выражениями, и мы отлично справились. Даже сегодня я не использую не-жадных в 99% всех случаев, по общему признанию, потому что я слишком ленив, чтобы искать синтаксис, но также потому, что случаи редко случаются там, где вы не могли просто написать хорошо законченный жадный. Например, чтобы соответствовать строке:

"(\\"|[^"])*"