很好地格式化输出到控制台,指定选项卡的数量

我正在生成将信息输出到控制台的脚本。 这些信息是某种有价值的统计数据。 非常像一个哈希。

所以一个值的名字可能是8个字符长,另一个是3.当我循环输出信息与两个\ t一些列没有正确alignment。

所以例如输出可能是这样的:

long value name 14 short 12 little 13 tiny 123421 long name again 912421 

我想要所有的值正确排列。 现在我正在这样做:

 puts "#{value_name} - \t\t #{value}" 

我怎么能说长名,只使用一个选项卡? 还是有另一种解决scheme?

通常有一个%10sprintfscheme,格式很好。
但是,我还没有使用ruby,所以你需要检查。


是的,有格式的printf。
上面的例子应该在10个字符的空间里alignment。
您可以根据列中最宽的字段进行格式化。

printf([port,]格式,arg …)

打印根据像sprintf这样的格式格式化的参数。 如果第一个参数是IO或其子类的实例,则打印redirect到该对象。 默认值是$ stdout的值。

只要你知道最大长度不超过20个字符:

 printf "%-20s %s\n", value_name, value 

如果你想使它更加dynamic,像这样的东西应该很好地工作:

 longest_key = data_hash.keys.max_by(&:length) data_hash.each do |key, value| printf "%-#{longest_key.length}s %s\n", key, value end 

之前几乎没有错误,但现在可以使用%运算符来使用大部分的printf语法:

 1.9.3-p194 :025 > " %-20s %05d" % ['hello', 12] => " hello 00012" 

当然你也可以使用预先计算的宽度:

 1.9.3-p194 :030 > "%-#{width}s %05x" % ['hello', 12] => "hello 0000c" 

string有一个内置的正是这个:

 x = {"foo"=>37, "something long"=>42, "between"=>99} x.each { |k, v| puts "#{k.ljust(20)} #{v}" } # Outputs: # foo 37 # something long 42 # between 99 

或者,如果你想要标签,你可以做一个小math(假设标签显示宽度为8),并写一个简短的显示function:

 def tab_pad(label, tab_stop = 4) label_tabs = label.length / 8 label.ljust(label.length + tab_stop - label_tabs, "\t") end x.each { |k, v| puts "#{tab_pad(k)}#{v}" } # Outputs: # foo 37 # something long 42 # between 99 

我写了一个东西

  • 自动检测列宽
  • 空间与空间
  • 数组[[],[],...]或散列数组[{},{},...]
  • 控制台窗口不检测列太宽

    列表= [[123,“SDLKFJSLDKFJSLDKFJLSDKJF”],[123456,“ffff”],]

array_maxes

 def array_maxes(lists) lists.reduce([]) do |maxes, list| list.each_with_index do |value, index| maxes[index] = [(maxes[index] || 0), value.to_s.length].max end maxes end end array_maxes(lists) # => [6, 24] 

puts_arrays_columns

 def puts_arrays_columns(lists) maxes = array_maxes(hashes) lists.each do |list| list.each_with_index do |value, index| print " #{value.to_s.rjust(maxes[index])}," end puts end end puts_arrays_columns(lists) # Output: # 123, SDLKFJSLDKFJSLDKFJLSDKJF, # 123456, ffff, 

还有一件事

 hashes = [ { "id" => 123, "name" => "SDLKFJSLDKFJSLDKFJLSDKJF" }, { "id" => 123456, "name" => "ffff" }, ] 

hash_maxes

 def hash_maxes(hashes) hashes.reduce({}) do |maxes, hash| hash.keys.each do |key| maxes[key] = [(maxes[key] || 0), key.to_s.length].max maxes[key] = [(maxes[key] || 0), hash[key].to_s.length].max end maxes end end hash_maxes(hashes) # => {"id"=>6, "name"=>24} 

puts_hashes_columns

 def puts_hashes_columns(hashes) maxes = hash_maxes(hashes) return if hashes.empty? # Headers hashes.first.each do |key, value| print " #{key.to_s.rjust(maxes[key])}," end puts hashes.each do |hash| hash.each do |key, value| print " #{value.to_s.rjust(maxes[key])}," end puts end end puts_hashes_columns(hashes) # Output: # id, name, # 123, SDLKFJSLDKFJSLDKFJLSDKJF, # 123456, ffff, 

编辑:修复在长度考虑的散列键。

 hashes = [ { id: 123, name: "DLKFJSDLKFJSLDKFJSDF", asdfasdf: :a }, { id: 123456, name: "ffff", asdfasdf: :ab }, ] hash_maxes(hashes) # => {:id=>6, :name=>20, :asdfasdf=>8} 

想要将列列入白名单?

 hashes.map{ |h| h.slice(:id, :name) } # => [ # { id: 123, name: "DLKFJSDLKFJSLDKFJSDF" }, # { id: 123456, name: "ffff" }, #] 

为了将来的参考和人谁看着这个或find它…使用gem。 我build议https://github.com/wbailey/command_line_reporter

你通常不想使用制表符,你想使用空格,并基本上设置你的“列”你自己,否则你碰到这些types的问题。