ruby регулярное выражение без глобального флага - PullRequest
2 голосов
/ 27 октября 2019

У меня проблема с регулярным выражением. У меня есть это регулярное выражение:

/(https|http):\/\/(kwagmire)\.(com)\/(embed)\/([a-zA-Z0-9]+)/i

, и оно корректно захватывает на https://regexr.com, но на Ruby on Rails все, что с

http://kwagmire.com/embed/1QgJVmCam

возвращает истинное значение, я думаю, потому что оноустанавливает его с флагом global, который мне не нужен.

Я пробовал match и scan, но все равно то же самое возвращает истинное значение, если ссылка видна. Я просто хочу, чтобы он был конкретным.

https://kwagmire.com/embed/1QgJVmCam < I want to return success this one is ok when testing on console

http://kwagmire.com/embed/1QgJVmCam < I want to return success also this on returns good

https.evil.com/http://jsitor.com/embed/1QgJVmCam < I want to return fail or nil, this one passes returns all match

facebook.com < I want to return fail or nil this one is good because its failing

https://google.com < I want to return fail or nil also this good failed
www.twitter.com < I want to return fail or nil

http://kwagmire.com/embed/1QgJVmCam/?onload(alert('asdfadsf')) < I want to return fail or nil, this one also is filing, good

http://kwagmire.com/embed/1QgJVmCam/   onload(alert('asdfadsf')) < I want to return fail or nil, this one returns match too but should faul

http://kwagmire.com/embed/1QgJVmCam/?onload(alert('asdfadsf')) < I want to return fail or nil, this one returns match too, this should fail

в основном я хочу это https://kwagmire.com/embed/1QgJVmCam, все остальное должно возвращать ноль или ложь. Есть ли простой способ без зацикливания? Я думаю, что решение этой проблемы - убрать глобальный флаг или g, но у вас есть такая опция? если да, то почему, если я сделаю это

, посмотрите i после /

/(https|http):\/\/(jsitor)\.(com)\/(embed)\/([a-zA-Z0-9]+)/i.match("http://jsitor.com/embed/1QgJVmCam/ onload(alert('asdfadsf'))")

и вернётесь, но это не получится

#<MatchData "http://jsitor.com/embed/1QgJVmCam" 1:"http" 2:"jsitor" 3:"com" 4:"embed" 5:"1QgJVmCam">

Ответы [ 3 ]

2 голосов
/ 27 октября 2019

Похоже, вам просто нужно либо ^ и $ в начале и конце вашего регулярного выражения, или еще лучше \A и \Z, чтобы отметить начало и конец всей строки (^ и$ работает, пока это одна строка).

Это говорит Руби, что он должен совпадать от начала до конца. Также «i» в конце не обязательно и может давать неправильные результаты.

Будет работать следующий модифицированный регулярный код.

/\A(https|http):\/\/(kwagmire)\.(com)\/(embed)\/([a-zA-Z0-9]+)\/?\Z/

Обратите внимание, что помимо \A и \Z я также добавил \/?, который допускает необязательный / в конце URL-адреса. Я также удалил i в конце, потому что вы на самом деле не хотите, чтобы регулярное выражение whole не чувствительно к регистру. Последняя часть ([a-zA-Z0-9]+) уже нечувствительна к регистру, как она объявлена ​​с помощью az и AZ.

myregex.match("http://kwagmire.com/embed/1QgJVmCa/?onload(alert('asdfadsf'))") возврат nil

myregex.match("http://kwagmire.com/embed/1QgJVmCam/") возврат #<MatchData "http://kwagmire.com/embed/1QgJVmCam/" 1:"http" 2:"kwagmire" 3:"com" 4:"embed" 5:"1QgJVmCam">

2 голосов
/ 27 октября 2019

Полагаю,

(?im)^https?:\/\/(?:w{3})?kwagmire\.com\/embed\/([a-zA-Z0-9]+)\/?$

может просто работать нормально.

Тест

re = /^https?:\/\/(?:w{3})?kwagmire\.com\/embed\/([a-zA-Z0-9]+)\/?$/im
str = 'https://kwagmire.com/embed/1QgJVmCam
http://kwagmire.com/embed/1QgJVmCam
https.evil.com/http://jsitor.com/embed/1QgJVmCam
facebook.com
https://google.com
www.twitter.com
http://kwagmire.com/embed/1QgJVmCam/?onload(alert(\'asdfadsf\'))
http://kwagmire.com/embed/1QgJVmCam/   onload(alert(\'asdfadsf\'))'

str.scan(re) do |match|
    puts match.to_s
end

Выход

["1QgJVmCam"]
["1QgJVmCam"]

Схема RegEx

jex.im визуализирует регулярные выражения:

enter image description here


Если вы хотите упростить / изменить / изучитьВыражение было объяснено на верхней правой панели regex101.com . Если хотите, вы также можете посмотреть в этой ссылке , как она будет сопоставляться с некоторыми примерами ввода.


1 голос
/ 27 октября 2019

Некоторые люди, столкнувшись с проблемой, думают: «Я знаю, я буду использовать регулярные выражения». Теперь у них есть две проблемы.

В Ruby есть модуль URI , который фактически анализирует URI и понимает их. Он побьет все носки практически любого регулярного выражения, когда дело доходит до фактической работы с URI.

Ввод:

input = ["https://kwagmire.com/embed/1QgJVmCam", "http://kwagmire.com/embed/1QgJVmCam", "https.evil.com/http://jsitor.com/embed/1QgJVmCam", "facebook.com", "https://google.com", "www.twitter.com", "http://kwagmire.com/embed/1QgJVmCam/?onload(alert('asdfadsf'))", "http://kwagmire.com/embed/1QgJVmCam/   onload(alert('asdfadsf'))"]
require 'uri'

# This assumes that the id is 9 characters
re =  /\A\/embed\/[\d|a-zA-Z]{9}\/?\Z/.freeze
clean = input.map do |line|
  begin
    uri = URI(line)
    if uri.host == 'kwagmire.com' && uri.path =~ re && !uri.query
      uri.to_s
    end
  rescue URI::InvalidURIError
    nil
  end
end.compact

Вывод:

["https://kwagmire.com/embed/1QgJVmCam", "http://kwagmire.com/embed/1QgJVmCam"]

Это позволяет вам использовать гораздо более простое регулярное выражение для проверки пути, вы также можете просто использовать uri.path.split('/') и полностью отказаться от регулярных выражений. Это также гарантирует, что вы имеете дело с действительным URI.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...