странное регулярное выражение нежадное поведение

Я пытаюсь понять, почему следующее регулярное выражение:\/.+?.ext\/ не работает так, как ожидалось в следующем предложении:http://slash1/slash2/slash3.ext/slash4.

Действительно, меня интересует только соответствие части URL-адреса с расширением «.ext». Сначала я подумал, что добавление нежадного символа уменьшит область действия до более близкого обратного слэша, но это не так, он действительно соответствует: //slash1/slash2/slash3.ext/

вот ссылка для проверки: http://rubular.com/r/CjJZFssQRF

РЕДАКТИРОВАТЬ: На всякий случай, если кто-то еще приземлится здесь, я, наконец, использовал следующее регулярное выражение: [^\/]+?\.ext обновленный рублер: http://rubular.com/r/FKcBQI50Lm


person Gomino    schedule 18.02.2014    source источник


Ответы (2)


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

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

\/[^\/]+?\.ext\/

(примечание: я избегал точки, которая является частью расширения, иначе оно соответствовало бы slash3aext)

демонстрация @ regex101

Я просто делаю предположение, но я думаю, что вы «думали» справа налево (when i encounter .ext i want everything until i encounter a slash to the left), когда вы должны думать слева направо, точно так же, как регулярное выражение проверяет вашу строку.

person KeyNone    schedule 18.02.2014
comment
Вы были правы, именно так я и думал. Спасибо за указание на это. - person Gomino; 18.02.2014
comment
@gomino Для неэффективных ?: вы можете прочитать об этом здесь. По сути, + будет соответствовать максимальному количеству символов, прежде чем будет удовлетворена следующая лексема (\.ext), а +? будет соответствовать минимальному количеству символов (но каждый раз минимум один! Для нуля до неограниченного вы бы использовали *). - person KeyNone; 18.02.2014
comment
Зачем ты снял. перед ленивым + т.е. \/[^\/]+?\.ext\/ вместо \/[^\/].+?\.ext\/ - person Gomino; 18.02.2014
comment
. соответствует каждому символу (кроме новой строки). [] обозначает класс символов, все внутри будет соответствовать. ^ отрицает класс символов, поэтому все внутри не может совпадать. Другими словами: [^\/]+ означает: match every character except / (в отличие от .: match every character). Я настоятельно рекомендую вам прочитать о регулярных выражениях (например, здесь), так как классы символов являются одним из основных . - person KeyNone; 18.02.2014

Попробуйте это вместо этого:

\/[^\/]+?.ext\/

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

^.*?\/[^\/]+?\.ext\/.*$
person JonM    schedule 18.02.2014
comment
Я больше пытаюсь понять причину, по которой нежадный '?' персонаж не работает в этом конкретном случае. В вашем решении это не нужно \/[^\/]+?.ext\/ эквивалентно \/[^\/]+.ext\/ - person Gomino; 18.02.2014