我试图让我的代码能够从命令行输入接受多个日志文件,以便根据不同的分隔符进行解析,并接受命令来解析某个日志文件的所有步骤。
它目前一次只能接受一个命令,并且它解析的日志文件是在代码中确定的,而不是变量@log_file
下的命令行输入:
@log_file = "07-07-14 to 07-13-14_debug.log"
@log_levels = ['DEBUG', 'INFO ', 'WARN ', 'ERROR', 'FATAL']
def error_sort
@log_levels.each do |log_level|
File.readlines(@log_file).each do |line|
if (line =~ /<#{log_level}>/ .. line =~ /<(?!#{log_level}).+>/) && line !~ /<(?!#{log_level}).+>/
File.open("#{log_level}.txt", "a") << line
end
end
end
end
def read_log(step)
File.readlines(@log_file).each do |line|
if line.match /Recording dut_serial_number/
File.open("step_#{step}", "a") << line
elsif (line =~ /Beginning step ##{step} / .. line =~ /Beginning step #(?!#{step}).+ /) && line !~ /Beginning step #(?!#{step}).+ /
File.open("step_#{step}", "a") << line
else
nil
end
end
end
command_line = ARGV[0..1]
ARGV.each do |num|
if command_line == ["--step", "#{num}"]
read_log("#{num}".to_i)
elsif command_line == ["--sort"]
error_sort
else
nil
end
end
思想?
答案 0 :(得分:2)
使用命令行参数解析像OptionParser这样的库可以轻松完成。
require 'optparse'
LOG_LEVELS = ['DEBUG', 'INFO ', 'WARN ', 'ERROR', 'FATAL']
def error_sort(log_file)
LOG_LEVELS.each do |log_level|
File.readlines(log_file).each do |line|
if (line =~ /<#{log_level}>/ .. line =~ /<(?!#{log_level}).+>/) && line !~ /<(?!#{log_level}).+>/
File.open("#{log_level}.txt", "a") << line
end
end
end
end
def read_log(log_file, step)
File.readlines(log_file).each do |line|
if line.match /Recording dut_serial_number/
File.open("step_#{step}", "a") << line
elsif (line =~ /Beginning step ##{step} / .. line =~ /Beginning step #(?!#{step}).+ /) && line !~ /Beginning step #(?!#{step}).+ /
File.open("step_#{step}", "a") << line
else
nil
end
end
end
options = {}
optparse = OptionParser.new do |opts|
opts.on("--sort", "Explain what this option does here.") do
options[:sort] = true
end
opts.on("--step NUM", Integer, "Explain what this option does here.") do |num|
options[:step] = num # num is automatically converted to an Integer
end
end
optparse.parse! # all non-option arguments remain in ARGV
log_file = ARGV[0]
if options[:sort]; error_sort(log_file); end
if options[:step]; read_log(log_file, options[:step]); end
有关OptionParser的更多信息:
修改强>
为了允许两次使用相同的标志,例如--step 3 --step 5
,我们可以将:step
地图中的options
条目更改为指定数字的数组,如下所示:
options = {:step => []}
optparse = OptionParser.new do |opts|
...
opts.on("--step NUM", Integer, "Explain what this option does here.") do |num|
options[:step] << num
end
end
然后使用:step
参数更改程序的语义,现在这是一个数组而不是一个数字:
unless options[:step].empty?
options[:step].each {|n| read_log(log_file, n)}
end
所有非选项参数都保留在ARGV
中,因此您可以轻松启用多个文件处理:
ARGV.each do |log_file|
if options[:sort]
error_sort(log_file)
end
unless options[:step].empty?
options[:step].each {|n| read_log(log_file, n)}
end
end
答案 1 :(得分:2)
您的代码需要一些重构。除了使用OptionParser之外,使用File.open
附加到文件效率很低。冥想:
LOG_FILE = "07-07-14 to 07-13-14_debug.log"
LOG_LEVELS = ['DEBUG', 'INFO ', 'WARN ', 'ERROR', 'FATAL']
def error_sort
LOG_LEVELS.each do |log_level|
File.open("#{log_level}.txt", "a") do |fo|
File.readlines(LOG_FILE).each do |line|
if (line =~ /<#{log_level}>/ .. line =~ /<(?!#{log_level}).+>/) && line !~ /<(?!#{log_level}).+>/
fo << line
end
end
end
end
end
def read_log(step)
File.open("step_#{step}", "a") do |fo|
File.readlines(LOG_FILE).each do |line|
if line[/Recording dut_serial_number/]
fo << line
elsif (line =~ /Beginning step ##{step} / .. line =~ /Beginning step #(?!#{step}).+ /) && line !~ /Beginning step #(?!#{step}).+ /
fo << line
else
;
end
end
end
end
在附加时反复打开和关闭文件会通过强制搜索到文件结尾,缓冲区在它们已满之前刷新等来减慢I / O子系统。相反,请根据需要打开文件,写入它在处理相同类型的数据时,然后关闭它以让系统重用文件句柄。