Supposons que je dispose de l'expression régulière suivante: /abcd/Supposons que je veuille vérifier l'entrée utilisateur par rapport à cette expression régulière et interdire la saisie de caractères non valides dans l'entrée. Lorsque l'utilisateur entre "ab", la correspondance avec l'expression rationnelle échoue, mais je ne peux pas refuser l'entrée de "a" puis de "b", car l'utilisateur ne peut pas saisir les 4 caractères à la fois (à l'exception du copier/coller). Donc, ce dont j'ai besoin ici, c'est d'une correspondance partielle qui vérifie si une chaîne incomplète peut potentiellement correspondre à une regex.
Java a quelque chose dans ce but: .hitEnd()
(décrit ici http://glaforge.appspot.com/article/incomplete-string-regex-matching ) python ne le fait pas en natif mais a ce paquet qui fait le travail : https://pypi.python.org/pypi/regex .
Je n'ai trouvé aucune solution pour cela dans js. Il a été demandé il y a des années: Javascript RegEx correspondance partielle Et même avant cela: Vérifier si string est le préfixe d'un Javascript RegExp
P.S. regex est personnalisé, supposons que l'utilisateur entre le regex lui-même, puis tente de saisir un texte correspondant à ce regex. La solution doit être une solution générale qui fonctionne pour les expressions rationnelles entrées au moment de l’exécution.
On dirait que vous avez de la chance, j'ai déjà implémenté ce genre de choses dans JS (ce qui fonctionne pour les patterns la plupart - peut-être que ça vous suffira). Voir ma réponse ici . Vous y trouverez également une démonstration de travail.
Il n'est pas nécessaire de dupliquer le code complet ici, je vais simplement énoncer le processus global:
RegExp
dans JS.abc
par (?:a|$)(?:b|$)(?:c|$)
[a-c]
deviendrait (?:[a-c]|$)
Si JavaScript avait des fonctionnalités regex plus avancées, cette transformation n'aurait peut-être pas été possible. Mais avec ses fonctionnalités limitées, il peut gérer la plupart des expressions rationnelles en entrée. Cela donnera des résultats incorrects sur les expressions rationnelles avec références arrières, cependant, si votre chaîne d'entrée se termine au milieu d'une correspondance en référence arrière (similaire à la correspondance de ^(\w+)\s+\1$
avec hello hel
).
Je pense que vous devez avoir 2 regex, un pour taper /a?b?c?d?/
et un pour tester à la fin tout en collant ou en laissant une entrée /abcd/
Ceci testera le numéro de téléphone valide:
const input = document.getElementById('input')
let oldVal = ''
input.addEventListener('keyup', e => {
if (/^\d{0,3}-?\d{0,3}-?\d{0,3}$/.test(e.target.value)){
oldVal = e.target.value
} else {
e.target.value = oldVal
}
})
input.addEventListener('blur', e => {
console.log(/^\d{3}-?\d{3}-?\d{3}-?$/.test(e.target.value) ? 'valid' : 'not valid')
})
<input id="input">
Et c'est le cas pour le nom de famille
const input = document.getElementById('input')
let oldVal = ''
input.addEventListener('keyup', e => {
if (/^[A-Z]?[a-z]*\s*[A-Z]?[a-z]*$/.test(e.target.value)){
oldVal = e.target.value
} else {
e.target.value = oldVal
}
})
input.addEventListener('blur', e => {
console.log(/^[A-Z][a-z]+\s+[A-Z][a-z]+$/.test(e.target.value) ? 'valid' : 'not valid')
})
<input id="input">
C’est la solution difficile pour ceux qui pensent qu’il n’ya pas de solution du tout: implémentez la version python ( https://bitbucket.org/mrabarnett/mrab-regex/src/4600a157989dc1671e4415ebe57aac53cfda2d8a/regex_regex/regex__regex/_gegex default & fileviewer = file-view-default ) en js. Donc c'est possible. Si quelqu'un a une réponse plus simple, il gagnera la prime.
Exemple utilisant le module python (expression régulière avec référence arrière):
$ pip install regex
$ python
>>> import regex
>>> regex.Regex(r'^(\w+)\s+\1$').fullmatch('abcd ab',partial=True)
<regex.Match object; span=(0, 7), match='abcd ab', partial=True>
Je soupçonne fortement (bien que je ne sois pas sûr à 100%) que le cas général de ce problème n'ait pas de solution de la même manière que le fameux "problème Haltin" de Turing (voir Problème indécidable ). Et même s’il existe une solution, ce ne sera probablement pas ce que les utilisateurs veulent réellement et, par conséquent, en fonction de votre rigueur, vous obtiendrez un UX mauvais à horrible.
Exemple:
Supposons que "RegEx cible" est [a,b]*c[a,b]*
. Supposons également que vous ayez produit un "test RegEx" [a,b]*c?[a,b]*
raisonnable au premier coup d'œil (deux noms c
dans la chaîne sont incorrects, yeah?) Et supposez que l'utilisateur actuel est aabcbb
mais il existe un type de frappe ce que l'utilisateur souhaitait en réalité, c'est aacbbb
. Il existe plusieurs façons de corriger cette faute de frappe:
c
et l'ajouter avant le premier b
- fonctionnera correctementb
et ajoute après c
- fonctionnera correctementc
avant le premier b
, puis supprimez l'ancien - Oups, nous interdisons cette entrée comme invalide et l'utilisateur deviendra fou parce qu'aucun humain normal ne peut comprendre une telle logique. Notez également que votre hitEnd
aura le même problème ici, sauf si vous interdisez à l'utilisateur de saisir des caractères au milieu de la zone de saisie, ce qui constitue un autre moyen de créer une interface utilisateur horrible.
Dans la vie réelle, il y aurait beaucoup d'exemples beaucoup plus compliqués qu'aucune de vos heuristiques intelligentes ne pourra prendre en compte correctement et va donc déranger les utilisateurs.
Alors que faire? Je pense que la seule chose que vous pouvez faire et que vous obtenez toujours une UX raisonnable est la chose la plus simple que vous puissiez faire, c’est-à-dire analyser votre "RegEx cible" pour déterminer le jeu de caractères autorisés et créer votre "test RegEx" [set of allowed chars]*
. Et oui, si le "RegEx cible" contient .
wildcart, vous ne pourrez pas effectuer de filtrage raisonnable.