Регулярное выражение для проверки длинных и сложных целей DNS - PullRequest
0 голосов
/ 05 декабря 2018

Записи DNS, которые я пытаюсь проверить, довольно длинные.Вот пример того, как может выглядеть структура:

qwer-0123a4bcd567890e1-uuuuu3xx.qwer-gfd-1e098765dcb4a3210.ps-sdlk-6.qwer.domain.com

Эти записи можно рассматривать как три отдельные части:

  1. qwer-0123a4bcd567890e1-uuuuu3xx.qwer-gfd-1e098765dcb4a3210.

    • Всегда начинается с qwer-
    • Далее17 буквенно-цифровых символов, a -, еще 8 буквенно-цифровых символов
    • , за которыми следуют qwer-gfd-
    • , за которыми следуют еще 17 буквенно-цифровых символов и .
  2. ps-sdlk-6

    • Всегда начинается с ps-sdlk-
    • , за которым следует либо один, либо два буквенно-цифровой.В этом случае это может быть ps-sdlk-6 или что-то вроде ps-sdlk-6e
  3. .qwer.domain.com

    • Цель домена всегда заканчивается .qwer.domain.com

Я взломал регулярное выражение и придумал это чудовище:

qwer-[\w]{17}-[\w]{8}.qwer-gfd-[\w]{17}.(.*)(qwer.domain.com)

Это решение довольноотвратительный и возвращает несколько групп совпадений, что не дает мне уверенности в точности.Я использую ruby ​​2.5, но в этом случае трудно импортировать не стандартные библиотеки.

Существует ли более разумное и полное / точное регулярное выражение для подтверждения достоверности этих целей DNS?Есть ли лучший способ сделать это без регулярных выражений?

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

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

PIECES = [['qwer'],
          ['0123a4bcd567890e1'.size],
          ['uuuuu3xx'.size, '.qwer'],
          ['gfd'],
          ['1e098765dcb4a3210'.size, '.ps'],
          ['sdlk'],
          [[1, 2], '.qwer.domain.com']].
  map do |a|
    Regexp.new(
      a.each_with_object('\A') do |o,s|
        case o
        when String
          s << o.gsub('.', '\.')
        when Integer
          s << "\\p{Alnum}{#{o}}"
        else # array
          s << "\\p{Alnum}{#{o.first},#{o.last}}"
        end
      end << '\z')
    end
  #=> [/\Aqwer\z/, /\A\p{Alnum}{17}\z/, /\A\p{Alnum}{8}\.qwer\z/,
  #    /\Agfd\z/, /\A\p{Alnum}{17}\.ps\z/, /\Asdlk\z/,
  #    /\A\p{Alnum}{1,2}\.qwer\.domain\.com\z/]

Обратите внимание, что я использовал одинарные кавычки в большинстве мест, чтобы иметь возможность писать, например, '\A' вместо "\\A".Однако двойные кавычки необходимы для двух строк, где выполняется интерполяция (#{o}).Я также использовал строки из этого примера, чтобы определить длины различных серий буквенно-цифровых символов, а также избежал точек и добавил якоря в простом коде.Я сделал это, чтобы уменьшить вероятность подсчета ошибок и помочь читателям кода понять, что делается.Хотя элементы PIECES (регулярные выражения) здесь используются для проверки строки, используемой для построения PIECES, что, конечно, не имеет значения, если предположить, что все строки, подлежащие проверке, будут иметь одинаковый шаблон.

def valid?(str)
  arr = str.split('-')
  return false unless arr.size == PIECES.size
  arr.zip(PIECES).all? { |s,r| s.match? r }
end

Если Enumerable # all? * Блок 1013 * возвращает false all?, немедленно возвращается false.Это иногда называют короткое замыкание поведение.

Для строки, приведенной в примере, str,

valid?(str)
  #=> true

Обратите внимание на следующие промежуточные вычисления.

str.split('-').zip(PIECES)
  #=> [["qwer", /\Aqwer\z/],
  #    ["0123a4bcd567890e1", /\A\p{Alnum}{17}\z/],
  #    ["uuuuu3xx.qwer", /\A\p{Alnum}{8}\.qwer\z/],
  #    ["gfd", /\Agfd\z/],
  #    ["1e098765dcb4a3210.ps", /\A\p{Alnum}{17}\.ps\z/],
  #    ["sdlk", /\Asdlk\z/],
  #    ["6.qwer.domain.com", /\A\p{Alnum}{1,2}\.qwer\.domain\.com\z/]]

Это может показаться излишним (и я не уверен, что это не так), но это облегчает отладку и тестирование, и если в будущем шаблон строки изменится (в определенных пределах), это должно бытьОтносительно легко изменить тест на соответствие (путем изменения указанного выше массива массивов, из которого получается PIECES).

0 голосов
/ 05 декабря 2018

Я думаю, учитывая ваши входные данные, у вас нет выбора, кроме уродливого регулярного выражения, например,

^qwer-\w{17}-\w{8}\.qwer-gfd-\w{17}\.ps-sdlk-\w{1,2}\.qwer\.domain\.com$

Обратите внимание, что я использовал \w, как вы, однако \w также соответствует _в виде буквенно-цифровых символов, поэтому вы можете заменить его на [A-Za-z0-9].Кроме того, . будет соответствовать любому символу, поэтому для конкретного соответствия . вам необходимо \. в вашем регулярном выражении.

Демонстрация на regex101.com

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...