【问题标题】:Regex matching a multi-line pattern匹配多行模式的正则表达式
【发布时间】:2019-01-31 08:43:55
【问题描述】:

我有一个日志文件test_list.txt,如下所示:

Processing SampleDocumentController#index (for 101.101.101.101 at 2020-12-12 12:00:00) [POST]
  Session ID: sdfgs923jks0dm23mlasf3da9asfjvyur
  Parameters: {"format"=>"xml", "controller"=>"sample_document", "q"=>"last_updated_at", "action"=>"index"}
Completed in 0.00529 (189 reqs/sec) | Rendering: 0.00007 (1%) | DB: 0.00126 (23%) | 200 OK [https://www.bars.com/sample/sample_document.lmx?]

我有一个正则表达式来捕获日志文件的方法和会话 ID:

regex = /\[([A-Z]+)\]\D+([a-zA-Z0-9]{32}$)/i

当我单独运行它时,它工作正常并返回捕获的字符串"POST""sdfgs923jks0dm23mlasf3da9asfjvyur"。但是,使用以下脚本test.rb:

File.open("test_list.txt").each do |li|
  if !li.nil?
    x = li.match(regex)
    if !x.nil?
      a, b = x.captures
      p a
      p b
    end
  end
end

在命令行中运行ruby test.rb 不会打印任何内容。

知道为什么它不适用于脚本吗?

【问题讨论】:

  • 您似乎正在逐行读取文件。将其作为单个字符串读入。

标签: ruby regex


【解决方案1】:

这是因为您的正则表达式仅在方法和会话 ID 都存在时才匹配。在您的日志文件中,它们位于不同的行上,并且没有一行包含两者。因此,没有一行与正则表达式匹配。

【讨论】:

【解决方案2】:

泽是对的。我想你误解了String#match,你通常想在布尔上下文中使用它。

您可能想使用scan。在您的情况下,您可以像这样扫描它:

string = File.read("test_list.txt")
        p string.scan(/(\[[A-Z]+\])|((?<=Session ID: )[a-zA-Z0-9]{33})/)

这将导致这样的事情:

[["[POST]", nil], [nil, "sdfgs923jks0dm23mlasf3da9asfjvyur"]]

你可以玩expression on regular

【讨论】:

  • 啜饮日志文件?这可能很慢。
  • @SergioTulentsev 我听到了,我仍在努力想出更好的方法来做到这一点。
  • @SergioTulentsev 谢谢你,它就像一个魅力!顺便说一句,我问题中的正则表达式只是我实际正则表达式的一部分,用于捕获日志文件条目所需的所有值。我实际的正则表达式有 12 个捕获组。在将 .txt 文件作为字符串传递(如您所建议的那样)并捕获所有值之后,我尝试了“扫描”和“匹配”。现在我需要想出一种方法来解析这些值中的每一个以将它们放入数据库中:)
  • @C.N.N.你可能是指我自己:D。无论如何,我很高兴它有所帮助
  • @tukan 哦,是的,我的错,我指的是你。谢谢一群朋友:)
【解决方案3】:

通过这样做,我让它完全按照我的意愿工作:

string = File.read("test_list.txt")
regex = /\[([A-Z]+)\]\D+([a-zA-Z0-9]{32}$)/

string.scan(regex).each do|x|
  puts x
end

如果说,我只想打印一个特定的捕获组,我只是为 x 添加数组索引号:

puts x[0]

puts x[1]

【讨论】:

    猜你喜欢
    • 2019-11-01
    • 2020-10-10
    • 2017-10-08
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多