如何计算文件特定部分之间的行数?

时间:2013-04-06 20:47:59

标签: ruby file parsing cucumber

所以,我正在尝试解析Cucumber文件(* .feature),以便确定每个场景有多少行。

档案示例:


    Scenario: Add two numbers 
       Given I have entered 50 into the calculator
       And I have entered 70 into the calculator
       When I press add
       Then the result should be 120 on the screen

    Scenario: Add many numbers
       Given I have entered 50 into the calculator
       And I have entered 20 into the calculator
       And I have entered 20 into the calculator
       And I have entered 30 into the calculator
       When I press add
       Then the result should be 120 on the screen

所以,我希望解析这个文件并获得如下结果:

场景:添加两个数字--->它有4行!

场景:添加多个数字--->它有6行!

这样做的最佳方法是什么?

4 个答案:

答案 0 :(得分:1)

你为什么不开始简单?像@FeRtoll建议的那样,逐行排列可能是最简单的解决方案。您可能正在寻找以下简单的内容:

scenario  = nil
scenarios = Hash.new{ |h,k| h[k] = 0 }

File.open("file_or_argv[0]_or_whatever.features").each do |line|
  next if line.strip.empty?

  if line[/^Scenario/]
    scenario = line
  else
    scenarios[scenario] += 1
  end
end

p scenarios

输出:

{"Scenario: Add two numbers \n"=>4, "Scenario: Add many numbers\n"=>6}

答案 1 :(得分:1)

Enumerable#slice_before几乎是为此量身定做的。

File.open('your cuke scenario') do |f|
  f.slice_before(/^\s*Scenario:/) do |scenario|
    title = scenario.shift.chomp
    ct = scenario.map(&:strip).reject(&:empty?).size
    puts "#{title} --> has #{ct} lines"
  end
end

答案 2 :(得分:0)

FeRtoll提出了一个很好的方法:按部分累积。解析它的最简单方法是擦除我可以忽略的部分(即注释),然后分成几部分:

file = ARGV[0] or raise "Please supply a file name to parse"

def preprocess file
  data = File.read(file)
  data.gsub! /#.+$/, ''    # strip (ignore) comments
  data.gsub! /@.+$/, ''    # strip (ignore) tags
  data.gsub! /[ \t]+$/, '' # trim trailing whitespace
  data.gsub! /^[ \t]+/, '' # trim leading whitespace
  data.split /\n\n+/       # multiple blanks separate sections
end

sections = {
  :scenarios    => [],
  :background   => nil,
  :feature      => nil,
  :examples     => nil
}

parts = preprocess file

parts.each do |part|
  first_line, *lines = part.split /\n/

  if first_line.include? "Scenario:"
    sections[:scenarios] << {
      :name  => first_line.strip,
      :lines => lines
    }
  end

  if first_line.include? "Feature:"
    sections[:feature] = {
      :name  => first_line.strip,
      :lines => lines
    }
  end

  if first_line.include? "Background:"
    sections[:background] = {
      :name  => first_line.strip,
      :lines => lines
    }
  end
  if first_line.include? "Examples:"
    sections[:examples] = {
      :name  => first_line.strip,
      :lines => lines
    }
  end
end

if sections[:feature]
  puts "Feature has #{sections[:feature][:lines].size} lines."
end

if sections[:background]
  puts "Background has #{sections[:background][:lines].size} steps."
end

puts "There are #{sections[:scenarios].size} scenarios:"
sections[:scenarios].each do |scenario|
  puts "  #{scenario[:name]} has #{scenario[:lines].size} steps"
end

if sections[:examples]
  puts "Examples has #{sections[:examples][:lines].size} lines."
end

HTH

答案 3 :(得分:0)

这是我正在研究的当前代码(基于Kyle Burton方法):

def get_scenarios_info
    @scenarios_info = [:scenario_name => "", :quantity_of_steps => []]
    @all_files.each do |file|
        line_counter = 0
        File.open(file).each_line do |line|
            line.chomp!
            next if line.empty?
            line_counter = line_counter + 1
            if line.include? "Scenario:"
                @scenarios_info << {:scenario_name => line, :scenario_line => line_counter, :feature_file => file, :quantity_of_steps => []}
                next
            end
            @scenarios_info.last[:quantity_of_steps] << line
        end
    end
    #TODO: fix me here!
    @scenarios_info.each do |scenario|
        if scenario[:scenario_name] == ""
            @scenarios_info.delete(scenario)
        end
        scenario[:quantity_of_steps] = scenario[:quantity_of_steps].size
    end
    puts @scenarios_info
end