Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have an array of JSON data being printed to the terminal (OS X) and I want the properties of that to be displayed in a table in the terminal.

Sample query:

aws ec2 describe-instances 
  | jq '[ .[] | .[] | .Instances[] as $ins
  | { groups: $ins.SecurityGroups[].GroupName,
    addresses: [ $ins.PrivateIpAddress, $ins.PublicIpAddress ],
    dns: $ins.PrivateDnsName,
    name: ($ins.Tags[] as $ts | $ts.Key == "Name" | $ts.Value ) }
  | select(.name | contains("prod")) ]'

Stated another way: I want to take the resulting data structure (array of object that contains properties 'addresses', 'groups', 'dns', 'name') and shove each object into a line of a table, inside the terminal/bash.

I don't mind to let the data be EOF-ed before the table starts drawing.

Example JSON:

[
  {
    "name": "prod-clusterX-01",
    "dns": "ip-10-34-XX-XX.eu-west-1.compute.internal",
    "addresses": [
      "10.34.XX.XX",
      "54.246.XX.XX"
    ],
    "groups": "prod-clusterX"
  },
  {
    "name": "prod-revproxy-a",
    "dns": "ip-10-0-XX-XX.eu-west-1.compute.internal",
    "addresses": [
      "10.0.XX.XX",
      "54.229.XX.XX"
    ],
    "groups": "prod-revproxy"
  }
]
share|improve this question
1  
can we see an example of the JSON? –  simon Aug 26 '13 at 10:30
    
Yes............ –  Henrik Aug 26 '13 at 11:25
    
are you open to solutions that depend upon, e.g. python, or third-party tools (at minimum sed, awk etc.)? –  simon Aug 26 '13 at 11:49

2 Answers 2

up vote 1 down vote accepted

Since OS X comes with Ruby:

sudo gem install json
sudo gem install table_print

For demo purposes, I've saved your JSON string to the file input, but you can pipe it to ruby as well:

ruby -e 'require "rubygems"; require "json"; require "table_print";
d = JSON.parse(ARGF.read);
d = d.map { |row| row["addresses"] = row["addresses"].join(", "); row }; 
tp.set :max_width, 120;
tp d' < input

This outputs:

NAME             | DNS                                       | GROUPS        | ADDRESSES
--------------------------------------------------------------------------------------------------------
prod-clusterX-01 | ip-10-34-XX-XX.eu-west-1.compute.internal | prod-clusterX | 10.34.XX.XX, 54.246.XX.XX
prod-revproxy-a  | ip-10-0-XX-XX.eu-west-1.compute.internal  | prod-revproxy | 10.0.XX.XX, 54.229.XX.XX
share|improve this answer
    
I've found the ordering of the table columns to be non-deterministic with table_print. Could be a bug—not sure. –  slhck Aug 26 '13 at 12:11
    
Nice. The reason that it's non-deterministic is probably that a Hash isn't ordered. There's the 'map' gem though, that you can probably replace the hash implementation in 'table_print' with. –  Henrik Aug 26 '13 at 20:28

Nice answer @slhck!

Here's some other examples:

aws ec2 describe-instances | jq '[ .[] | .[] | .Instances[] as $ins
  | select(.Platform == null)
  | { instance_type: $ins.InstanceType,
      name: ($ins.Tags[] as $ts | select($ts.Key == "Name") | $ts.Value ),
      security_groups: $ins.SecurityGroups[].GroupName,
      launched: $ins.LaunchTime } ]' | ./to-table.rb

to-table.rb will check for arrays itself now:

#!/usr/bin/env ruby

require "json"
require "table_print"

def join_arrays row
  row.keys.each do |key|
    row[key] = row[key].join(', ') if row[key].respond_to? :join
  end
end

d = JSON.parse(ARGF.read).each { |row| join_arrays row }
w = `/usr/bin/env tput cols`.to_i
tp.set :max_width, w
tp d

(PS: tput cols yields the number of columns that the current bash has.)

share|improve this answer
    
Good addition. So it turns out you know Ruby anyway :) (Sometimes OS X users are surprised by what they can do in their terminal with pre-installed tools.) –  slhck Aug 26 '13 at 20:36
    
Thanks =). Yes, knowing a bit of programming is very helpful. This week we're getting new Macs and we'll be installing Boxen on them and share some development environments across the team! =) –  Henrik Aug 26 '13 at 20:42

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.