Сопоставьте все IP-адреса в тексте с регулярным выражением - PullRequest
0 голосов
/ 13 июня 2018

Допустим, у меня есть строка, которая может содержать один или несколько IP-адресов.Как сопоставить их все и только действительные, используя regex в ruby?

В настоящее время мое решение выглядит так:

IP_ADDR_REGEX = %r{
  \b
  (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
  \b
}x

Это хорошо работает, когда IP разделяются пробелами, например, извлекает192.168.1.1 из текста bla bla 192.168.1.1 bla.Однако в этом случае он все равно извлекает 192.168.1.1: bla bla 192.168.1.1.1.1 bla.

Как сделать так, чтобы это не совпадало с такими случаями?т.е. когда это 192.168.1.1.1.1, мое регулярное выражение не должно возвращать совпадение.Я искал много решений по этой проблеме, но не смог найти то, что я хочу.Я также пытался найти решение самостоятельно, сопоставляя только пробелы в конце (потому что \b также соответствует символу .), но я не мог заставить его работать.Спасибо

Ответы [ 2 ]

0 голосов
/ 13 июня 2018

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

IP_ADDR_REGEX = %r{
  \b                                        # Word boundary
  (?<!\d\.)                                 # Negative lookbehind: no "X." before
  (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
  \b                                        # Word boundary
  (?!\.\d)                                  # Negative lookahead: no ".X" after
}x

Regex demo # 1

Обратите внимание, что в случае, если вы хотите ограничить совпадения только подстроками, разделенными пробелами, используйте

IP_ADDR_REGEX = %r{
  (?<!\S)                                    # Position not preceded with non-whitespace char
  (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
  (?!\S)                                    # Position not followed with non-whitespace char
}x

Regex demo # 2

Обратите внимание, что группа без захвата (?:...) облегчит использование метода String#scan для сбора всех совпадений из строк.

0 голосов
/ 13 июня 2018

Вам следует заменить слово сопоставления границ \b на явный пробел (и сопоставить его с положительным прогнозом, поскольку вы не хотите, чтобы оно возвращалось):

IP_ADDR_REGEX = %r{
  (?<=\s|^)
  (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
  (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
  (?=\s|$)
}x

main ▶ 'bla bla 192.168.1.1.1.1 bla'[IP_ADDR_REGEX]
#⇒ nil
main ▶ 'bla bla 192.168.1.1.1 bla'[IP_ADDR_REGEX]
#⇒ nil
main ▶ 'bla bla 192.168.1.1 bla'[IP_ADDR_REGEX]
#⇒ "192.168.1.1"
...