Мне нужно извлечь фактическое имя файла из URL-адреса.
https://www.corp.com/lib/file.html?id=aahttps://www.corp.com/lib/file.html?id=aa/bbhttps://www.corp.com/lib/file.htmlОжидаемый результат: file.html во всех случаях. Примечание. В имени файла не обязательно должна быть точка, это может быть просто file, и тогда в качестве результата должно вернуться file.
В случае
https://www.corp.com/lib/https://www.corp.com/lib/?id=aahttps://www.corp.com/lib/?id=aa/bbОжидаемый результат должен быть ""
Уже некоторое время тестирую регулярное выражение, но просто не могу заставить группировку работать из-за существующего (или нет) вопросительного знака. Я знаю, что косая черта в запросе, скорее всего, не появится, но если это возможно, я бы хотел принять это во внимание, поскольку веб-браузер, похоже, принимает ее без кодирования.
Я не могу сделать это программно по шагам, потому что инструмент, который я использую, обрабатывает только регулярные выражения.
Есть идеи?
«Я не могу сделать это программно по шагам, потому что инструмент, который я использую, обрабатывает только регулярные выражения.»: что это за инструмент? Итак, это инструмент, который принимает, скажем, два аргумента: URL-адрес и регулярное выражение?
@Dai На самом деле это не какой-то язык, это инструмент для расширения текста :-)
вот так: (?<=(?<!/)/)\w+\.\w+(?=$|\?)?
Вас волнуют «неочевидные» URL-адреса, такие как https://corp.com/lib/? Или https://corp.com/lib/file.html/? Или https://corp.com/lib.
@JoachimSauer большое спасибо, что заметил это, моя вина! да, если «имя файла» отсутствует, то результатом должна быть пустая строка «». Я обновил вопрос.
@DuesserBaest, это так здорово :-) большое спасибо, я допустил ошибку в своем вопросе, очень извините. В имени файла не обязательно должна быть точка. в этом. Это может быть «corp.com/filename» без точки. Очень сожалею о пропавшем футляре.
тогда откуда ты знаешь, что bb в https://www.corp.com/lib/?id=aa/bb не файл?
@DuesserBaest необязательный знак вопроса и все, что следует за ним, всегда можно игнорировать. Извините за плохое описание.





Проверьте, изменив URL-адрес с https://www.corp.com/lib/file.html на https://www.corp.com/lib/file надеюсь, что это сработает.
Пытаться:
^.*\K(?<=(?<!/)/)[.\w]+(?=\?)|([^?\n]*\?[^?\n]*)(*SKIP)(*FAIL)|[.\w]+$
См.: regex101
Объяснение:
есть три случая:
?:^.*\K: с начала строки сопоставить все и забыть, пока...(?<!/)/)[.\w]+(?=\?): вы найдете строку, которой предшествует одна /, но не две // и за которой следует ??([^?\n]*\?[^?\n]*): если строка содержит вопросительный знак...(*SKIP)(*FAIL): выбрось это[.\w]+$Это очень хороший ответ :-) хотя я не совсем ясно изложил вопрос, в «имени файла» не обязательно должна быть точка. Верри, извините за плохое описание. Такое ощущение, что нужно просто изменить часть \w.\w, но потом она ломается и соответствует другим частям. :-)
@steb, можешь ли ты получить доступ к группам захвата? есть ли у вас доступ к группам сброса ветвей? попробуйте (?|^.*(?<=(?<!/)/)(\w+\.\w+)(?=\?)|([^?\n]*\?[^ ?\n]*)(*SKIP)(*FAIL)|([.\w]+)$); результаты будут в группе 1
Или, если вы можете использовать \K^.*\K(?<=(?<!/)/)[.\w]+(?=\?)|([^?\n]*\? [^?\n]*)(*SKIP)(*FAIL)|[.\w]+$ будет работать
Это УДИВИТЕЛЬНО, последний вариант с \K работает идеально. Огромное спасибо @DuesserBaest. Ты король регулярных выражений!
Его можно сократить до ^[^#?]*/\K[^/?#]*(?![^#?])
@CasimiretHippolyte да, вы абсолютно правы, похоже, это тоже работает нормально :-) просто экранирует передние косые черты, и это работает в моем случае. Очень здорово получилось!
Просто чтобы вы знали: я один из сторонников, это хорошая идея, и она хорошо объяснена. Я не знаю, почему люди минусуют, не оставляя комментариев, это раздражающая игра.
@bobblebubble у меня есть подозрения, что кто-то может отрицать многие мои ответы, но это нормально. Я отвечаю, чтобы помочь и научиться самому, а не ради хороших оценок или чего-то еще :) очень нравится ваш ответ - очень элегантно!
Для использования с PCRE, возможно, этого будет достаточно:
^[^?]*/\K[\w.-]*
Посмотрите это демо по адресу regex101 (\n в демо предназначено только для многострочного тестирования)
Идея состоит в том, чтобы сопоставить любые символы , которые не являются ? до последней косой черты. С помощью \K сбросьте начало сообщаемого совпадения и оттуда сопоставьте любое количество слов-символов, точку, тире (также пустое).
Но если вы не хотите пустых совпадений и используете [\w.]+ , это не сработает (демо) из-за возврата. Чтобы это работало, вы можете использовать глагол PCRE COMMIT , чтобы не возвращаться после совпадения с последней косой чертой. Вероятно, вместо него можно использовать SKIP с аналогичным эффектом.
^[^?]*/(*COMMIT)\K[\w.-]+
Еще одно демо на regex101 (@DuesserBaest, я позаимствовал твою витрину)
Очень ясное и лаконичное регулярное выражение ++
@anubhava, спасибо! :)
...какой язык вы используете? Практически в каждом языке есть библиотека для анализа URI. Вам следует использовать это вместо регулярного выражения, если это возможно, потому что в противном случае ваше регулярное выражение будет сбито с толку подстроками, похожими на имя файла, скажем, в части имени пользователя, или если есть имя хоста, похожее на имя файла - например.
https://file.html:file.html:file.html/file.html/file.html?filehtml=file.html— это действительный URI, понимаете (еслиfile.htmlопределен на вашем DNS-сервере)