2
votes

Ruby regex sans indicateur global

J'ai un problème de regex. J'ai cette expression régulière:

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

et cela capture correctement sur https://regexr.com a> mais sur Ruby on Rails, tout ce qui contient

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

renvoie une valeur de vérité, je pense parce qu'il la définit avec le drapeau global que je ne porte pas ' Je veux.

J'ai essayé match et scan mais toujours la même chose renvoie une valeur de vérité si le lien est vu. Je veux juste que ce soit précis.

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 que https://kwagmire.com/embed/1QgJVmCam tout le reste devrait renvoyer nil ou faux. y a-t-il un moyen facile sans boucle? Je pense que la solution sur celui-ci est de supprimer le drapeau global ou g mais avez-vous cette option? Si oui, pourquoi si je fais cela?

voir le i après /

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

et renvoie mais cela devrait échouer

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


5 commentaires

Pouvez-vous être plus précis sur ce que vous voulez réaliser? Pouvez-vous fournir des liens de test de ce que vous voulez faire correspondre et de quels liens ne devraient pas correspondre?


@allenbrkn vérifie le texte avant < je l'ai modifié


Pour ce que ça vaut, ce n'est pas une question sur les rails. Ceci est une question sur le rubis pur.


Plutôt que d'essayer d'écrire une regex, qui pour URI est complexe, utilisez la classe URI de Ruby qui l'a déjà écrite et qui fonctionne, et qui vous permet de diviser un chemin en ses composants et de les vérifier individuellement. En particulier, regardez split < / code> et analyser .


Vous devez formuler votre question en termes de ce que vous voulez réaliser, sans référence à une expression régulière . Autrement dit, vous souhaitez tester un certain nombre de chaînes. Un seul réussit le test. Quel est le test? C'est ainsi que vous devez formuler votre question. Après avoir fait cela, vous pouvez présenter l'expression régulière que vous avez essayée et expliquer pourquoi elle ne fonctionne pas. Enfin, oubliez de spéculer sur les raisons pour lesquelles l'expression régulière ne fonctionne pas.


3 Réponses :


2
votes

Je suppose que

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

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

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

Circuit RegEx

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

entrez la description de l'image ici


Si vous souhaitez simplifier / modifier / explorer l'expression, cela a été expliqué dans le panneau supérieur droit de regex101 .com . Si vous le souhaitez, vous pouvez également regarder ce lien , comment il correspondrait contre quelques exemples d'entrées.



3 commentaires

désolé monsieur cela ne fonctionne pas. Je pensais à regex_without_global.match ('https://kwagmire.com/embed/1QgJV‌ mCam') renvoyer la vérité regex_without_global.match ('https://kwagmire.com/ embed / 1QgJV‌ mCam /? evilevil ') renvoie nil


Avec ruby, ^ et $ correspondent toujours au début et à la fin de la ligne, et le modificateur m permet au point de correspondre aux nouvelles lignes.


@CasimiretHippolyte mais ça me donne juste un tableau vide quand j'ai essayé son approche tho



2
votes

Il semble que vous ayez simplement besoin de ^ et $ au début et à la fin de votre expression régulière, ou mieux encore de \ A et \ Z pour marquer le début et la fin de la chaîne entière ( ^ et $ fonctionnent tant qu'il s'agit d'une seule ligne).

Cela indique à Ruby qu'il doit correspondre du début à la fin. De plus, 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 \ A et \ Z j'ai également ajouté \ /? qui permet un / à la fin de l'url. J'ai également supprimé le i à la fin parce que vous ne voulez pas vraiment que l'expression régulière entière soit insensible à la casse. La dernière partie ([a-zA-Z0-9] +) est déjà insensible à la casse par la façon dont elle est déclarée 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 #


2 commentaires

yow monsieur je pense que c'est ça. c'est tout ce que je veux. Je savais qu'il y avait un moyen simple de ne pas boucler cela parce que je sais quelle sera l'URL. J'ai utilisé une manière similaire en javascript avant d'oublier. Je vous remercie! @randall


j'ai également ajouté ceci \ A et \ Z mais sur regexr.com , il dit que littéralement A c'est pourquoi je ne l'ai pas fait utilise le.



1
votes

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

Ruby a le module URI a> qui analyse les URI et les comprend. Il battra les chaussettes de presque toutes les expressions régulières quand il s'agit de travailler avec les URI.

Entrée:

["https://kwagmire.com/embed/1QgJVmCam", "http://kwagmire.com/embed/1QgJVmCam"]
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:

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'))"]

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


0 commentaires