Попытка захвата значения в захваченном значении - PullRequest
0 голосов
/ 15 марта 2019

Я пытаюсь проанализировать данные из строки, подобной этой

"Lorem ipsum dolor sit amet, IP: 111.111.111.111, 222.222.222.222, 333.333.333.333\r\n adipiscing elit, sed do eiusmod\r\n tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud"

Я пытаюсь получить такие значения, как это:

  • сообщение: "Lorem ipsum dolor sit amet, IP: 111.111.111.111, 222.222.222.222, 333.333.333.333\r\n adipiscing elit, sed do eiusmod\r\n tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud"
  • ip: "111.111.111.111, 222.222.222.222, 333.333.333.333"

Может быть произвольно много IP-адресов, включая ноль.

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

[PARSER]
Name syslog-rfc3164
Format regex
Regex /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
Time_Key    time
Time_Format %b %d %H:%M:%S
Time_Format %Y-%m-%dT%H:%M:%S.%L
Time_Keep   On

Благодаря Кэри и Алексею вот решение:

\A(?<whole>.*?((?<=IP: )(?<ip>(?<four_threes>\d{1,3}(?:\.\d{1,3}){3})(?:, \g<four_threes>)*)).*?)\z

https://rubular.com/r/Kgh5EXMCA0lkew

РЕДАКТИРОВАТЬ

Я понял, что в некоторых строках отсутствует шаблон "IP: ...", что приводит к ошибке синтаксического анализа.

string1: "Lorem ipsum dolor sit amet, IP: 111.111.111.111, 222.222.222.222, 333.333.333.333\r\n adipiscing elit, sed do eiusmod\r\n tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud"

string2: "Lorem ipsum dolor sit amet, \r\n adipiscing elit, sed do eiusmod\r\n tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud"

Я пытался применить * (0 или больше) к совпадению имени группы ip, но я не смог заставить его работать.Любая идея, как я могу это сделать?

Ответы [ 2 ]

2 голосов
/ 15 марта 2019
str = 'Lorem, IP: 111.111.111.111, 222.222.222.222, 333.333.333.333\r\n adipiscing'

r = /
    \A                     # match the beginning of the string
    (?<whole>              # begin named group 'whole' 
      .*?                  # match >= 0 characters 
      (?<ip>               # begin named group 'ip'
        (?<four_threes>    # begin a named group 'four_threes'
          \d{1,3}          # match 1-3 digits
          (?:              # begin a non-capture group
            \.             # match a period
            \d{1,3}        # match 1-3 digits
          ){3}             # close non-capture group and execute same 3 times
        )                  # close capture group 'four_threes'
        (?:                # begin a non-capture group
          ,\p{Space}       # match ', '
          \g<four_threes>  # execute subexpression named 'four_threes'
        )*                 # close non-capture group and execute same >= 0 times
      )                    # close capture group 'ip'
      .*                   # match >= 0 characters
    )                      # close capture group 'whole'
    /x                     # free-spacing regex definition mode

m = str.match(r)
m[:whole] 
  #=> "Lorem, IP: 111.111.111.111, 222.222.222.222, 333.333.333.333\\r\\n adipiscing" 
m[:ip]
  #=> "111.111.111.111, 222.222.222.222, 333.333.333.333" 

Условное выражение условно написано:

/\A(?<whole>.*?(?<ip>(?<four_threes>\d{1,3}(?:\.\d{1,3}){3})(?:, \g<four_threes>)*).*)/

При определении регулярного выражения в свободном интервале пространства должны быть каким-то образом защищены, иначе они будут удалены до разбора выражения.Я использовал \p{Space}, но [[:space:]], \s и [ ] (пробел в классе символов) также могут быть использованы.(Все, кроме последнего, соответствуют символу пробела.) Когда регулярное выражение записывается обычным способом, можно использовать пробел, как показано выше.

\g<four_threes> - это вызов подвыражения (поиск "Субэкспрессия звонков").Их использование экономит набор текста и снижает вероятность ошибок.Если это, третий названный захват, не нужен, его, конечно, можно заменить.

0 голосов
/ 15 марта 2019

Вы можете использовать /([0-9]_\.)+/ как очень простое регулярное выражение (там гораздо лучше регулярное выражение IPv4).

Затем, используя .scan(...) в вашей строке, вы получите результаты в виде массива.

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