Je suis nouveau ici alors je ferai de mon mieux.

J'ai une ligne de texte contenant différentes informations sur la voiture.

65101km, Berline, Manuelle, 18131A, FWD, Occasion, 5.5L / 100km, Toyota, camry, SE, {AC, Sièges chauffants, Miroirs chauffants, Entrée sans clé}, 2010

J'essaie d'écrire une expression régulière qui correspondra à une combinaison de lettres et de chiffres ne se terminant PAS par "km" dans cette ligne. C'est le numéro de série de la voiture qui peut différer d'un constructeur à l'autre. Par exemple:

18FO724A, 18131A, 19BF723A

Ce sont des numéros de série différents de différents modèles de voitures.

J'ai essayé ceci:

/((?:[a-zA-Z]+[0-9]+[^km]$|[0-9]+[a-zA-Z])[a-zA-Z0-9])/

Mais il continue de rendre le nombre de kilomètres

65101km

Alors que la réponse dont j'ai besoin est

18131A

N'importe quelle aide fera l'affaire. Merci

0
tester_s25 20 nov. 2018 à 05:05

3 réponses

Meilleure réponse

D'après les exemples que vous avez fournis, il semble que vos numéros de série commencent toujours par un chiffre et se terminent par une lettre - si ce n'est pas le cas, reportez-vous à mon commentaire et lisez-le ce qu'il faudra pour mieux vous aider.

Ce modèle devrait fonctionner:

/(\d+[a-z0-9]+[a-z](?<!km\b))(?:,|$)/i

Cela nécessite les conditions suivantes:

  • \d+ commence par au moins un ou plusieurs + chiffres \d
  • [a-z0-9]+ suivi d'un caractère alphanumérique [a-z0-9], une ou plusieurs fois +
  • (?<!km\b))(?:,|$) lookahead négatif qui affirme que la chaîne se termine par une virgule , ou la fin de la chaîne $, mais pas si elle vient après les lettres km (?<!km\b)

Cela utilise un seul groupe de capture (...) donc vous n'incluez pas la virgule , qui accompagne l'intégralité de la correspondance

Consultez-le sur regex101

3
K.Dᴀᴠɪs 20 nov. 2018 à 06:52

Je crois comprendre que, étant donné une chaîne, vous souhaitez extraire toutes les sous-chaînes ayant les propriétés suivantes:

  • la sous-chaîne est précédée d'une virgule ou commence la chaîne et est suivie d'une virgule ou termine la chaîne;
  • la sous-chaîne ne contient que des chiffres et des lettres majuscules;
  • la sous-chaîne contient au moins un chiffre;
  • la sous-chaîne contient au moins une lettre majuscule; et
  • la sous-chaîne ne peut pas se terminer par la chaîne "km".

La chaîne de test est la suivante.

str = "65101km,Sedan,Manual,18131A,FWD,Used,5.5L/100km,Toyota,camry,SE," +
      "{AC, Heated Seats, Heated Mirrors, Keyless Entry},2010,208A1,28km1"

Notez que j'ai ajouté la chaîne donnée dans la question avec ",208A1,28km1".

Vous pouvez extraire les sous-chaînes souhaitées en utilisant la méthode String # scan avec l'expression régulière suivante.

r = /
    (?<=\A|,)      # match the beginning of the string or a comma in a positive lookbehind
    [\p{Upper}\d]  # match a digit or uppercase letter in character class
    *              # perform above match zero or more times     
    (?:            # begin a non-capture group
      \d           # match a digit
      \p{Upper}    # match an uppercase letter
      |            # or
      \p{Upper}    # match an uppercase letter
      \d           # match one or more digits
    )              # end non-capture group
    [\p{Upper}\d]  # match a digit or uppercase letter in character class
    *              # perform above match zero or more times     
    (?<!km)        # do not match 'km' (negative lookbehing)
    (?=,|\z)       # match a comma or end of the string (positive lookahead)
    /x             # free-spacing regex definition mode

str.scan(r)
   #=> ["18131A", "208A1"]

Vous pouvez également le faire en quatre étapes plus simples.

str.split(',').select do |s| s.match?(/\A\p{Alnum}+\z/) &&
                             s.match?(/\p{Alpha}/) &&
                             s.match?(/\p{Digit}/) &&
                             !s.end_with?("km")
                      end
  #=> ["18131A", "208A1"]

La documentation des \p{} constructions peut être trouvée en recherchant sur la même chose dans Regexp. Ils sont similaires aux classes de parenthèses POSIX , qui sont documentées dans le même fichier.

L'expression régulière est classiquement écrite (c'est-à-dire, pas en mode d'espacement libre) comme suit. J'ai également remplacé \p{Upper} par son abréviation, \p{Lu}.

 r = /(?<=\A|,)[\p{Lu}\d]*(?:\d\p{Lu}|\p{Lu}\d)[\p{Lu}\d]*(?<!km)(?=,|\z)/
1
Cary Swoveland 16 juin 2019 à 20:14

Je commencerais par diviser cette ligne en éléments par la virgule, puis en appliquant l'expression régulière à chaque élément:

input = "65101km,Sedan,Manual,18131A,FWD,Used,5.5L/100km,Toyota," \
        "camry,SE,{AC, Heated Seats, Heated Mirrors, Keyless Entry},2010"
input.split(',').grep(/^(?!.*km)\d+\p{l}+$/)
#⇒ ["18131A"]

Ce qui précède renvoie un tableau, donc vous voudrez probablement le gérer d'une manière ou d'une autre (par exemple avec first.)

L'expression régulière elle-même correspond à tous les éléments, suivant le modèle \d+\p{l}+ qui ne correspondent pas à km (recherche négative au début.)

0
Aleksei Matiushkin 20 nov. 2018 à 07:28