web-dev-qa-db-fra.com

Comment correspond un personnage OR rien avec l'expression régulière

J'essaie de prendre un bloc de nombres qui peut ou non avoir des séparateurs et de les renvoyer dans un format standard. En utilisant le SSN comme exemple:

ex1="An example 123-45-6789"
ex2="123.45.6789 some more things"
ex3="123456789 thank you Ruby may I have another"

devrait tous aller dans une méthode qui retourne "123-45-6789" En gros, tout (sauf rien) à l'exception d'un chiffre ou d'une lettre doit renvoyer un SSN au format XXX-XX-XXXX. La partie agrafante est un moyen pour les expressions régulières d'identifier qu'il ne peut y avoir rien.

Ce que j'ai jusqu'à présent dans l'identification de mon SSN:

def format_ssns(string)
  string.scan(/\d{3}[^0-9a-zA-Z]{1}\d{2}[^0-9a-zA-Z]{1}\d{4}/).to_a
end

Cela semble fonctionner pour tout ce que je prévois SAUF lorsqu'il n'y a rien. "123456789" ne fonctionne pas. Puis-je utiliser des expressions régulières dans ce cas pour identifier un manque?

15
notthehoff

Avez-vous essayé de faire correspondre 0 ou 1 caractères entre vos numéros?

\d{3}[^0-9a-zA-Z]{0,1}\d{2}[^0-9a-zA-Z]{0,1}\d{4}
7
user3188140

Cela a déjà été partagé dans un commentaire, mais juste pour fournir une réponse complète-ish ...

Vous avez ces outils à votre disposition:

  • x correspond à x exactement une fois
  • x{a,b} correspond à x entre a et b fois
  • x{a,} correspond à x au moins a fois
  • x{,b} correspond à x jusqu'à (un maximum de) b fois
  • x* correspond à x zéro fois ou plus (identique à x{0,})
  • x+ correspond à x une ou plusieurs fois (identique à x{1,})
  • x? correspond à x zéro ou une fois (identique à x{0,1})

Donc, vous voulez utiliser ce dernier, car c'est exactement ce que vous recherchez (zéro ou une fois).

/\d{3}[^0-9a-zA-Z]?\d{2}[^0-9a-zA-Z]?\d{4}/
36
Dan Tao

Votre expression rationnelle actuelle autorisera 123-45[6789, sans parler de tous les types de caractères Unicode et de caractères de contrôle. Dans le cas extrême:

123
45師6789

est considéré comme correspondant à votre expression rationnelle.

Vous pouvez utiliser backreference pour vous assurer que le séparateur est identique.

/\d{3}([.-]?)\d{2}\1\d{4}/

[.-]? correspondra soit ., - ou rien (en raison du quantificateur optionnel ?). Ce qui correspond ici sera utilisé pour s'assurer que le second séparateur est identique via backreference.

2
nhahtdh

Whelp ... on dirait que je viens de trouver ma propre réponse, mais tout indice d'amélioration serait utile.

def format_ssns(string)
  string.scan(/\d{3}[^0-9a-zA-Z]{0,1}\d{2}[^0-9a-zA-Z]{1}\d{4}/).to_a
end

Semble faire l'affaire.

0
notthehoff