-2

我正在尝试从这样的行中解析数据

"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,包括零个。

我正在使用带有单个正则表达式的流利位。这是 fluent-bit 解析器定义的示例:

[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

感谢 Cary 和 Aleksei,这是解决方案:

\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 组名称匹配,但我无法使其工作。知道我该怎么做吗?

4

2 回答 2

2
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:]], \sand [ ](字符类中的空格)也可以使用。(除了最后一个匹配一个空白字符。)当正则表达式以传统方式编写时,可以使用空格,如上所示。

\g<four_threes>是一个子表达式调用(搜索“子表达式调用”)。它们的使用可以节省打字并减少出错的机会。如果不想要第三个命名的捕获,它当然可以被替换掉。

于 2019-03-15T02:15:45.123 回答
0

您可以将/([0-9]_\.)+/其用作非常基本的正则表达式(那里有更好的 IPv4 正则表达式)。

然后通过.scan(...)在您的字符串上使用,您将获得作为数组的结果。

于 2019-03-15T01:14:04.223 回答