Регулярное выражение "пустой диапазон в char ошибке класса"

Я получил регулярное выражение в моем коде, которое соответствует шаблону url и забросило ошибку:

/^(http|https):\/\/([\w-]+\.)+[\w-]+([\w- .\/?%&=]*)?$/

Ошибка была "пустой диапазон в char ошибке класса". Я нашел причину этого в части ([\w- .\/?%&=]*)?. Кажется, Ruby распознает - в \w- . как оператор диапазона, а не буква -. После добавления выхода в тире проблема была решена.

Но исходное регулярное выражение хорошо работало на машинах моих коллег. Мы используем ту же версию osx, rails и ruby: Ruby версия ruby ​​1.9.3p194, rails - 3.1.6, а osx - 10.7.5. И после того, как мы развернули код на нашем сервере Heroku, все отлично работало. Почему только моя среда имела ошибку в отношении этого регулярного выражения? Каков механизм интерпретации регулярных выражений Ruby?

Ответ 1

Я могу реплицировать эту ошибку на Ruby 1.9.3p194 (исправление 2012-04-20 версия 35410) [i686-linux], установленная на Ubuntu 12.04.1 LTS с использованием rvm 1.13.4. Однако это не должно быть ошибкой, зависящей от версии. На самом деле, я удивлен, что он работал на других машинах вообще.

A более простая демонстрация, которая не работает так же хорошо:

"abcd" =~ /[\w- ]/

Это связано с тем, что [\w- ] интерпретируется как "диапазон, начинающийся с любого символа слова до пробела (или пробела)", а не с символьным классом, содержащим слово, дефис или пробел, что и было предназначена.

Документация регулярного выражения Ruby:

В классе символов дефис (-) является метасимволом, обозначающим инклюзивный диапазон символов. [abcd] эквивалентен [a-d]. За диапазоном может следовать другой диапазон, поэтому [abcdwxyz] эквивалентен [a-dw-z]. Порядок, в котором диапазоны или отдельные символы появляются внутри класса символов, не имеет значения.

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

"abcd" =~ /[-\w ]/