2 votes

Regex Ruby sans drapeau global

J'ai un problème de regex. J'ai cette expression :

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

et ceci capture correctement sur https://regexr.com mais avec Ruby on Rails, tout ce qui comporte

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

renvoie une valeur vraie, je pense que c'est parce qu'il la définit avec la fonction global drapeau que je ne veux pas.

J'ai essayé match y scan mais le même renvoie une valeur vraie si le lien est vu. Je veux juste que ce soit spécifique.

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 it's 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 failing, good

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

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

En gros, je veux ceci https://kwagmire.com/embed/1QgJVmCam tout le reste devrait retourner nil ou false. y a-t-il un moyen simple sans boucle ? Je pense que la solution est d'enlever l'indicateur global ou g mais avez-vous cette option ? Si oui, pourquoi le faire ?

voir le i après /

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

et renvoie mais ceci devrait échouer

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

2voto

Emma Points 1

Je suppose,

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

pourrait tout simplement fonctionner correctement.

Test

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

Sortie

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

Circuit RegEx

jex.im visualise les expressions régulières :

enter image description here


Si vous souhaitez simplifier/modifier/explorer l'expression, elle a été expliquée dans le panneau supérieur droit de la page regex101.com . Si vous le souhaitez, vous pouvez également regarder en ce lien comment il se comporterait par rapport à certains échantillons.


2voto

Randall Coding Points 357

On dirait que vous avez juste besoin ^ y $ au début et à la fin de votre regex, ou mieux encore \A y \Z pour marquer le début et la fin de la chaîne entière ( ^ y $ pour autant qu'il s'agisse d'une seule ligne).

Cela indique à Ruby qu'il doit correspondre du début à la fin. Le "i" à la fin n'est pas nécessaire et peut donner des résultats incorrects.

La regex modifiée suivante fonctionnera.

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

Notez qu'en plus de l \A y \Z J'ai également ajouté \/? qui permet d'ajouter une option / à la fin de l'url. J'ai également supprimé le i à la fin parce que vous ne voulez pas réellement le tout le site pour être insensible à la casse. La dernière partie ([a-zA-Z0-9]+) est déjà insensible à la casse par la façon dont il est déclaré avec a-z et A-Z.

myregex.match("http://kwagmire.com/embed/1QgJVmCa/?onload(alert('asdfadsf'))") renvoie à nil

myregex.match("http://kwagmire.com/embed/1QgJVmCam/") renvoie à #<MatchData "http://kwagmire.com/embed/1QgJVmCam/" 1:"http" 2:"kwagmire" 3:"com" 4:"embed" 5:"1QgJVmCam">

1voto

papirtiger Points 1870

Certaines personnes, lorsqu'elles sont confrontées à un problème, pensent "Je sais, je vais utiliser des expressions régulières". Maintenant, ils ont deux problèmes.

Ruby a le Module URI qui analyse réellement les URI et les comprend. Il surpasse presque toutes les expressions régulières lorsqu'il s'agit de travailler avec les URI.

Entrée :

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

Sortie :

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

Cela vous permet d'utiliser une expression régulière beaucoup plus simple pour vérifier le chemin, vous pourriez aussi simplement utiliser uri.path.split('/') et de renoncer complètement à une expression rationnelle. Cela garantit également que vous avez affaire à un URI valide.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X