Проверьте строку запроса URL с помощью регулярного выражения
Я пытаюсь проверить строку запроса с помощью регулярного выражения. Обратите внимание, что я не пытаюсь сопоставить значения, но проверяю его синтаксис. Я делаю это, чтобы практиковать регулярные выражения, поэтому я был бы признателен за помощь, а не за "использование этой библиотеки", хотя мне помогло бы узнать, как это могло быть сделано в библиотеке, поэтому покажите мне, если она у вас есть.
Итак, это были бы предпосылки:
- Это должно начинаться с вопросительного знака.
- Он может содержать ключи со значениями или без значений, разделенных знаком равенства, пары, разделенные амперсандом.
У меня довольно далеко, но у меня возникают проблемы с сопоставлением в регулярном выражении, что знак равенства и амперсанд должны быть в определенном порядке без необходимости повторять группы совпадений. Вот что у меня так далеко:
#^\?([\w\-]+((&|=)([\w\-]+)*)*)?$#
Это правильно совпадает ?abc=123&def=345
, но это также неправильно соответствует, например, ?abc=123=456
,
Я мог бы пойти излишне и сделать что-то вроде...
/^\?([\w\-]+=?([\w\-]+)?(&[\w\-]+(=?[\w\-]*)?)*)?$/
... но я не хочу повторять одинаковые группы совпадений.
Как я могу сказать регулярному выражению, что разделители между значениями должны перебирать &
а также =
без повторения совпадений групп или отслеживания катастрофического спина?
Спасибо.
Редактировать:
Я хотел бы уточнить, что это не предназначено для реальной реализации; для этого следует использовать встроенную библиотеку на вашем языке, которая, скорее всего, доступна. Этот вопрос задается, потому что я хочу улучшить свои навыки регулярных выражений, и анализ строки запроса показался мне полезным.
7 ответов
Кажется, это то, что вы хотите:
^\?([\w-]+(=[\w-]*)?(&[\w-]+(=[\w-]*)?)*)?$
Посмотреть демо
Это рассматривает каждую "пару" как ключ, за которым следует необязательное значение (которое может быть пустым), и имеет первую пару, за которой следует необязательное &
затем другая пара, и все выражение (за исключением ведущих?
) не является обязательным. Это предотвращает совпадение ?&abc=def
Также обратите внимание, что дефис не нужно экранировать, когда он последний в классе символов, что позволяет немного упростить.
Кажется, вы хотите разрешить дефисы в любом месте ключей или значений. Если ключи должны быть свободны от дефисов:
^\?(\w+(=[\w-]*)?(&\w+(=[\w-]*)?)*)?$
Вы можете использовать это регулярное выражение:
^\?([^=]+=[^=]+&)+[^=]+(=[^=]+)?$
Что это делает:
NODE EXPLANATION
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
\? '?'
--------------------------------------------------------------------------------
( group and capture to \1 (1 or more times
(matching the most amount possible)):
--------------------------------------------------------------------------------
[^=]+ any character except: '=' (1 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
= '='
--------------------------------------------------------------------------------
[^=]+ any character except: '=' (1 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
& '&'
--------------------------------------------------------------------------------
)+ end of \1 (NOTE: because you are using a
quantifier on this capture, only the LAST
repetition of the captured pattern will be
stored in \1)
--------------------------------------------------------------------------------
[^=]+ any character except: '=' (1 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
( group and capture to \2 (optional
(matching the most amount possible)):
--------------------------------------------------------------------------------
= '='
--------------------------------------------------------------------------------
[^=]+ any character except: '=' (1 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
)? end of \2 (NOTE: because you are using a
quantifier on this capture, only the LAST
repetition of the captured pattern will be
stored in \2)
--------------------------------------------------------------------------------
$ before an optional \n, and the end of the
string
Я согласен с Энди Лестером, но возможное решение для регулярных выражений
#^\?([\w-]+=[\w-]*(&[\w-]+=[\w-]*))?$#
что очень похоже на то, что вы опубликовали.
Я не проверял это, и вы не сказали, какой язык вы используете, поэтому может потребоваться небольшая настройка.
Это может быть работа не для регулярных выражений, а для существующих инструментов на выбранном вами языке. Регулярные выражения - это не волшебная палочка, которую вы махаете при каждой проблеме, которая связана со строками. Вы, вероятно, хотите использовать существующий код, который уже был написан, протестирован и отлажен.
В PHP используйте parse_url
функция.
Perl: URI
модуль.
Рубин: URI
модуль.
.NET: класс "Ури"
Я сделал это.
function isValidURL(url) {
// based off https://mathiasbynens.be/demo/url-regex. testing https://regex101.com/r/pyrDTK/2
var pattern = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:\/?)(?:(?:\?(?:(?!&|\?)(?:\S))+=(?:(?!&|\?)(?:\S))+)(?:&(?:(?!&|\?)(?:\S))+=(?:(?!&|\?)(?:\S))+)*)?$/iuS;
return pattern.test(url);
}
База: https://mathiasbynens.be/demo/url-regex
Тестирование: https://regex101.com/r/pyrDTK/4/
/^\?([\w-]+(=[\w.\-:%+]*)?(&[\w-]+(=[\w.\-:%+]*)?)*)?$/
\w = [a-zA-Z0-9_]
? знак равно
над поддержкой регулярных выражений,
a-z A-Z 0-9 _ . - : % +
в значении параметра
Когда вам нужно проверить очень сложный URL-адрес, вы можете использовать это регулярное выражение
`^(https|ftp|http|ftps):\/\/([a-z\d_]+\.)?(([a-zA-Z\d_]+)(\.[a-zA-Z]{2,6}))(\/[a-zA-Z\d_\%\-=\+]+)*(\?)?([a-zA-Z\d=_\+\%\-&\{\}\:]+)?`