我需要你的帮助。我在ruby上编写一个脚本,它解析日志文件。但我不能为这样的日志写一个简单的正则表达式。请帮帮我。以下是日志中字符串的示例:
2014-01-09T06:16:53.766841+00:00 heroku[router]: at=info method=POST path=/logs/save_personal_data host=services.pocketplaylab.com fwd="5.13.87.91" dyno=web.10 connect=1ms service=42ms status=200 bytes=16
2014-01-09T06:16:53.772938+00:00 heroku[router]: at=info method=POST path=/api/users/100002844291023 host=services.pocketplaylab.com fwd="46.195.178.244" dyno=web.6 connect=2ms service=43ms status=200 bytes=52
2014-01-09T06:16:53.765430+00:00 heroku[router]: at=info method=GET path=/api/users/100005936523817/get_friends_progress host=services.pocketplaylab.com fwd="5.13.87.91" dyno=web.11 connect=1ms service=47ms status=200 bytes=7498
2014-01-09T06:16:53.760472+00:00 heroku[router]: at=info method=POST path=/api/users/1770684197 host=services.pocketplaylab.com fwd="74.139.217.81" dyno=web.5 connect=1ms service=17ms status=200 bytes=681
2014-01-09T06:15:15.893505+00:00 heroku[router]: at=info method=GET path=/api/users/1686318645/get_friends_progress host=services.pocketplaylab.com fwd="1.125.42.139" dyno=web.3 connect=8ms service=90ms status=200 bytes=7534
2014-01-09T06:16:53.768188+00:00 heroku[router]: at=info method=GET path=/api/users/100005936523817/get_friends_score host=services.pocketplaylab.com fwd="5.13.87.91" dyno=web.13 connect=2ms service=46ms status=200 bytes=9355
2014-01-09T06:15:17.858874+00:00 heroku[router]: at=info method=POST path=/api/users/1145906359 host=services.pocketplaylab.com fwd="107.220.72.53" dyno=web.14 connect=2ms service=362ms status=200 bytes=52
2014-01-09T06:16:53.797975+00:00 heroku[router]: at=info method=GET path=/api/users/100000622081059/count_pending_messages host=services.pocketplaylab.com fwd="174.239.6.42" dyno=web.12 connect=1ms service=20ms status=200 bytes=33
2014-01-09T06:16:53.796869+00:00 heroku[router]: at=info method=GET path=/api/users/100004683190675/get_friends_score host=services.pocketplaylab.com fwd="99.138.1.64" dyno=web.12 connect=2ms service=55ms status=200 bytes=16881
我的代码(正在更新):
#!/usr/bin/env ruby
require 'csv'
sample_logs = File.readlines "/home/railsroger/Playlab_test/sample.log"
file_name = ARGV.last
result_parse = []
CSV.open(file_name, "wb") do |csv_line|
csv_line << ['URL', 'Dyno', 'Connect', 'Service']
sample_logs.each_with_index do |sample_log, idx|
path = sample_log.scan(/path=([^\s]+)/).first.first
dyno = sample_log.scan(/dyno=([^\s]+)/).first.first
connect = sample_log.scan(/connect=([^\s]+)/).first.first
service = sample_log.scan(/service=([^\s]+)/).first.first
result_parse = [path, dyno, connect, service]
csv_line << result_parse
end
end
感谢。
答案 0 :(得分:3)
好的,要写你的正则表达式,你需要的是找到所有这些some_variable=some_data
的夫妻。
以下是如何做到这一点:
/\S*=\S*/ #
\S* # match any non-whitespace-character, 0-n times
= # match the equal sign
\S* # match any non-whitespace-character, 0-n times
这将与夫妻相匹配。要提取数据,请使用捕获组。
您可以在括号(xxx)
中包含要提取的内容,以获取变量名称和值。
/(\S*)=(\S*)/
(\S*) # capture the name
(\S*) # capture the value
因此,对于您可以执行的每个日志行:
line_of_log.scan(/(\S*)=(\S*)\s/)
要了解会发生什么,并创建正则表达式,我建议您始终使用https://regex101.com/这样的工具进行试用,真正有助于了解正在发生的事情。
这将返回如下数组:
[["at", "info"],
["method", "POST"],
["path", "/api/online/platforms/facebook_canvas/users/100002266342173/add_ticket"],
["host", "services.pocketplaylab.com"],
["fwd", "\"94.66.255.106\""],
["dyno", "web.12"],
["connect", "12ms"],
["service", "21ms"],
["status", "200"],
["bytes", "78"]]
不,你可以遍历数组并创建某种对象或哈希来使用。
scanresult.inject({}) do |obj, pair|
obj[pair[0].to_sym] = pair[1]
obj
end
答案 1 :(得分:1)
我不是正则表达式专家,也知道下面的代码闻起来 - ))但你可以把它作为一个起点。
lines = File.readlines 'sample.log'
lines.each_with_index do |line, idx|
path = line.scan(/path=([^\s]+)/).first.first
dyno = line.scan(/dyno=([^\s]+)/).first.first
connect = line.scan(/connect=([^\s]+)/).first.first
service = line.scan(/service=([^\s]+)/).first.first
puts "#{path} #{dyno} #{connect} #{service}"
end
Edit suggested by Wiktor Stribiżew,显然更简洁,更好。我更喜欢它比我的。为历史原因保留上述代码 - ))
lines.each_with_index do |line, idx|
path = line[/path=([^\s]+)/, 1]
dyno = line[/dyno=([^\s]+)/, 1]
connect = line[/connect=([^\s]+)/, 1]
service = line[/service=([^\s]+)/, 1]
puts "#{path} #{dyno} #{connect} #{service}"
end
答案 2 :(得分:0)
解决方案是使用named captures:
String#match(/dyno=(?<dyno>\S+)/)
将捕获dyno字符串。您可以展开正则表达式以匹配更多。
你可以在这里举例说明: http://rubular.com/r/4XcovTiqh3 - 通过一些试验和错误,您可以找到正确的正则表达式
parser = log.match(/dyno=(?<dyno>\S+)/)
将返回一个MatchData对象,您可以从中获取匹配的dyno:
parser['dyno']
一旦你完成正则表达式以从每一行捕获更多内容,并且如果你使用Ruby 2.4或更高版本,你也可以使用named_captures
来获得所有匹配组的漂亮哈希