comment valider les caractères ET les mots dans regex?


neokio

Le contexte

J'ai besoin d'un peu de code qui prend une chaîne mathématique très simple et exécute la eval()fonction PHP . Par exemple ...

  $math = '25 * (233 - 1.5)';
  echo eval("return $math;"); // returns 5787.5

Cependant, eval()c'est assez dangereux entre de mauvaises mains, donc la variable doit être nettoyée. Pour ce qui précède, par exemple, un simple preg_replace serait ...

  $math = '25 * (233 - 1.5)';
  $replace = '/[^0-9\(\)\.\,\+\-\*\/\s]/';
  $math = preg_replace($replace, '', $math);
  echo eval("return $math;"); // returns 5787.5

... qui garantit $mathne contient que des caractères valides ... .,+-*/, des espaces et des chiffres, et aucun code malveillant.

La question

Je veux laisser quelques mots très spécifiques (fonctions mathématiques PHP), tels que pow, pi, min, max, etc.

Quelle est la manière la plus propre de valider les caractères et les mots dans les regex?

Donc, si on lui donne cette chaîne ...

pow(25,2) / pi(); hack the pentagon;

... comment supprimer tout ce qui n'était pas dans l' $replaceexpression régulière, mais conserver les mots powet pi?

Le quatrième oiseau

En utilisant php, vous pouvez faire correspondre les mots que vous ne souhaitez pas supprimer et utiliser une approche (* SKIP) (* FAIL) .

Vous pouvez également raccourcir la classe de caractères en supprimant les barres obliques inverses, et si vous utilisez un délimiteur différent de celui /de php, vous n'avez pas non plus à échapper le/

Lorsque vous remplacez les caractères correspondants dans la classe de caractères par une chaîne vide, vous pouvez utiliser un quantificateur +pour faire correspondre une ou plusieurs correspondances consécutives et effectuer un seul remplacement.

\b(?:p(?:i|ow)|m(?:in|ax))\b(*SKIP)(*FAIL)|[^0-9().,+*/\s-]+

Le motif correspond

  • \b(?:p(?:i|ow)|m(?:in|ax))\bMatch soit pi pow minoumax
  • (*SKIP)(*FAIL)| Les correspondances jusqu'à présent ne doivent pas faire partie du résultat
  • [^0-9().,+*/\s-]+Correspond à 1+ fois n'importe quel caractère sauf les caractères listés dans la classe de caractères annulée

Démo Regex

Si vous ne voulez pas les espaces au début et à la fin, vous pouvez envisager de couper $math

$math = 'pow(25,2) / pi(); hack the pentagon;';
$replace = '~\b(?:p(?:i|ow)|m(?:in|ax))\b(*SKIP)(*FAIL)|[^0-9().,+*/\s-]+~';
$math = preg_replace($replace, '', $math);
echo eval("return $math;"); // returns 198.94367886487

Articles connexes


Limiter les mots et non les caractères dans Laravel

daugaard47 J'utilise Laravel 5.7 et je me demandais quelle serait la bonne manière de limiter le nombre de mots, pas de caractères, dans une description que je tire de la base de données et que je produis vers une lame / vue. Cela fonctionne actuellement en aj

Trouver des caractères uniques dans les mots avec RegEx

LeMage Rouge Je souhaite utiliser RegEx pour faire correspondre les caractères d'une séquence qui n'apparaissent qu'une seule fois dans ce mot. Ainsi, par exemple, armored armadilloles seules correspondances seraient e, iet . Ma première tentative a été d'util

Comment regex, et ajouter "-" entre les mots ?

roux ACTUALISÉ J'ai regardé dans l'ancien interweb pour voir s'il y avait un moyen de le réexercer dans le cadre d'une méthode de remplacement que je suis en train de faire : str.replace(/\w[AZ]/gm, "-") ceciEstUnRegex dans ceci : ceci-est-un-regex J'ai essayé