Регулярное выражение, которое будет соответствовать комбинации букв и цифр, НЕ заканчивающихся на «км» - PullRequest
0 голосов
/ 20 ноября 2018

Я новичок здесь, поэтому я буду стараться изо всех сил.

У меня есть строка текста, содержащая различную информацию об автомобиле.

65101 км, седан, механическая коробка, 18131A, FWD, Б / у, 5,5 л / 100 км, Toyota, camry, SE, {AC, подогрев сидений, подогрев зеркал, вход без ключа}, 2010

Я пытаюсь написать регулярное выражение, которое будет соответствовать комбинации букв и цифр, НЕ заканчивающихся на «км» в этой строке.Это серийный номер автомобиля, который может отличаться от одного автопроизводителя к другому.Например:

18FO724A, 18131A, 19BF723A

Это разные серийные номера разных моделей автомобилей.

Я пробовал это:

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

Но он продолжает возвращать количество километров

65101km

, в то время как мне нужен ответ

18131A

Любая помощь подойдет.Спасибо

Ответы [ 3 ]

0 голосов
/ 20 ноября 2018

Из предоставленных вами примеров кажется, что ваши серийные номера всегда будут начинаться с цифры и заканчиваться буквой - если это не так, то обратитесь к мой комментарий и прочитайте, что нужно сделать, чтобы помочь вам лучше.

Этот шаблон должен работать:

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

Для этого необходимы следующие условия:

  • \d+ начинается с минимальной одной или нескольких + цифр \d
  • [a-z0-9]+, за которым следует любой буквенно-цифровой символ [a-z0-9], один или несколько раз +
  • (?<!km\b))(?:,|$) отрицательный прогноз, который утверждает, что строка заканчивается либо запятой ,, либо концом строки $, но не в том случае, если она идет после букв km (?<!km\b)

При этом используется одна группа захвата (...), поэтому вы не включаете запятую ,, которая идет со всем соответствием

См. На regex101

0 голосов
/ 20 ноября 2018

Я бы начал с разбиения этой строки на элементы запятой, а затем применял бы регулярное выражение к каждому элементу:

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

Вышеприведенное возвращает массив, поэтому вы, вероятно, захотите как-то с ним работать (например, с помощью first.)

Само регулярное выражение соответствует всем элементам, следуя шаблону \d+\p{l}+, который не соответствует km ( отрицательный взгляд в начале.)

0 голосов
/ 20 ноября 2018

Насколько я понимаю, при наличии строки вы хотите извлечь все подстроки, имеющие следующие свойства:

  • подстроке предшествует запятая или начинается строка, после которой следует запятая или конец строки;
  • подстрока содержит только цифры и заглавные буквы;
  • подстрока содержит хотя бы одну цифру;
  • подстрока содержит хотя бы одну заглавную букву; и
  • подстрока не может заканчиваться строкой "km".

Тестовая строка следующая.

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

Обратите внимание, что я добавил строку, приведенную в вопросе, с ",208A1,28km1".

Вы можете извлечь нужные подстроки, используя метод String # scan со следующим регулярным выражением.

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

Кроме того, вы можете сделать это в четыре простых шага.

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

Документацию для \p{} конструкций можно найти, выполнив поиск по этому же адресу в Regexp . Они аналогичны классам скобок POSIX , которые описаны в одном файле.

Регулярное выражение записывается условно (то есть, не в режиме свободного пробела) следующим образом. Я также заменил \p{Upper} на его сокращение \p{Lu}.

 r = /(?<=\A|,)[\p{Lu}\d]*(?:\d\p{Lu}|\p{Lu}\d)[\p{Lu}\d]*(?<!km)(?=,|\z)/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...