GitHub

Overview

JSON is an excellent data interchange format and rapidly becoming the preferred format for Web APIs. Thusfar, most of the tools to process it are very limited. Yet, when working in JavaScript, JSON is fluid and natural.

Why can't command-line JavaScript be easy?

Underscore-CLI can be a simple pretty printer:

cat data.json | underscore print --color

example.png

Or it can form the backbone of a rich, full-powered JavaScript command-line, inspired by "perl -pe", and doing for structured data what sed, awk, and grep do for text.

cat example-data/earthporn.json | underscore extract 'data.children' | underscore pluck data | underscore pluck title

See Real World Example for the output and more examples.

Underscore-CLI is:

  • FLEXIBLE - THE "Swiss Army knife" tool for processing JSON data - can be used as a simple pretty-printer, or as a full-powered JavaScript command-line
  • POWERFUL - Exposes the full power and functionality of [underscore.js] (http://documentcloud.github.com/underscore/) (plus [underscore.string] (https://github.com/epeli/underscore.string), json:select, and CoffeeScript)
  • SIMPLE - Makes it simple to write JavaScript one-liners similar to using "perl -pe"
  • CHAINED - Multiple command invokations can be chained together to create a data processing pipeline
  • MULTI-FORMAT - Rich support for input / output formats - pretty-printing, strict JSON, etc. See [Data Formats] (#data_formats)
  • DOCUMENTED - Excellent command-line documentation with multiple examples for every command

A Bit More Explanation ...

Underscore-CLI is built on Node.js, which is less than a 4M download and very easy to install. Node.js is rapidly gaining mindshare as a tool for writing scalable services in JavaScript.

Unfortutately, out-of-the-box, Node.js is a pretty horrible as a command-line tool. This is what it takes to simply echo stdin:

cat foo.json | node -e '
  var data = "";
  process.stdin.setEncoding("utf8");
  process.stdin.on("data", function (d) {
    data = data + d;
  });
  process.stdin.on("end", function () {
    // put all your code here
    console.log(data);
  });
  process.stdin.resume();
'

Ugly. Underscore-CLI handles all the verbose boilerplate, making it easy to do simple data manipulations:

echo '[1, 2, 3, 4]' | underscore process 'map(data, function (value) { return value+1 })'

If you are used to seeing "_.map", note that because we arn't worried about keeping the global namespace clean, many useful functions (including all of underscore.js) are exposed as globals.

Of course 'mapping' a function to a dataset is super common, so as a shortcut, it's exposed as a first-class command, and the expression you provide is auto-wrapped in "function (value, key, list) { return ... }".

echo '[1, 2, 3, 4]' | underscore map 'value+1'

Also, while you can pipe data in, if the data is just a string like the example above, there's a shortcut for that too:

underscore -d '[1, 2, 3, 4]' map 'value+1'

Or if it's stored in a file, and you want to write the output to another file:

underscore -i data.json map 'value+1' -o output.json

Here's what it takes to increment the minor version number for an NPM package (straight from our Makefile):

underscore -i package.json process 'vv=data.version.split("."),vv[2]++,data.version=vv.join("."),data' -o package.json

Installing Underscore-CLI

Installing Node.js (command-line JavaScript)

Installing Node.js is easy. It's only a 4M download:

Download Node.js

Alternatively, if you do homebrew, you can:

brew install node

For more details on what Node.js is, see this StackOverflow question

Installing

npm install -g underscore-cli
underscore help

Documentation

.

Usage

If you run the tool without any arguments, this is what prints out:

"Usage: underscore [--in |--data |--nodata] [--infmt ] [--out ] [--outfmt ] [--quiet] [--strict] [--color] [--text] [--trace] [--coffee] [--js] Commands: help [command] Print more detailed help and examples for a specific command type Print the type of the input data: {object, array, number, string, boolean, null, undefined} print Output the data without any transformations. Can be used to pretty-print JSON data. pretty Output the data without any transformations. Can be used to pretty-print JSON data. (defaults output format to 'pretty') run Runs arbitrary JS code. Use for CLI Javascripting. process Run arbitrary JS against the input data. Expression Args: (data) extract Extract a field from the input data. Also supports field1.field2.field3 map Map each value from a list/object through a transformation expression whose arguments are (value, key, list).' reduce Boil a list down to a single value by successively combining each element with a running total. Expression args: (total, value, key, list) reduceRight Right-associative version of reduce. ie, 1 + (2 + (3 + 4)). Expression args: (total, value, key, list) select Run a 'JSON Selector' query against the input data. See jsonselect.org. find Return the first value for which the expression Return a truish value. Expression args: (value, key, list) filter Return an array of all values that make the expression true. Expression args: (value, key, list) reject Return an array of all values that make the expression false. Expression args: (value, key, list) flatten Flattens a nested array (the nesting can be to any depth). If you pass '--shallow', the array will only be flattened a single level. pluck Extract a single property from a list of objects keys Retrieve all the names of an object's properties. values Retrieve all the values of an object's properties. extend

Read the original on github.com ↗