diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/Gemfile | 5 | ||||
-rw-r--r-- | docs/Gemfile.lock | 53 | ||||
-rw-r--r-- | docs/Rakefile | 55 | ||||
-rw-r--r-- | docs/content/2.download/default.yml | 78 | ||||
-rwxr-xr-x | docs/content/2.download/linux_x86_64/jq | bin | 385542 -> 0 bytes | |||
-rwxr-xr-x | docs/content/2.download/osx_64/jq | bin | 190556 -> 0 bytes | |||
-rw-r--r-- | docs/content/3.manual/manual.yml | 407 | ||||
-rw-r--r-- | docs/site.yml | 4 | ||||
-rw-r--r-- | docs/templates/index.liquid | 4 |
9 files changed, 501 insertions, 105 deletions
diff --git a/docs/Gemfile b/docs/Gemfile new file mode 100644 index 00000000..f06950f6 --- /dev/null +++ b/docs/Gemfile @@ -0,0 +1,5 @@ +source :rubygems + +gem "bonsai" +gem "maruku" +gem "ronn" diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock new file mode 100644 index 00000000..ccbc84fe --- /dev/null +++ b/docs/Gemfile.lock @@ -0,0 +1,53 @@ +GEM + remote: http://rubygems.org/ + specs: + activesupport (3.2.9) + i18n (~> 0.6) + multi_json (~> 1.0) + addressable (2.3.2) + bonsai (1.4.7) + activesupport (>= 3.0.3) + builder (>= 3.0.0) + i18n (>= 0.5.0) + launchy (>= 0.3.7) + liquid (>= 2.2.2) + maruku (>= 0.6.0) + rack + sass + sinatra (>= 1.0) + tilt (>= 1.3) + watch (>= 0.1.0) + builder (3.1.4) + hpricot (0.8.6) + i18n (0.6.1) + launchy (2.1.2) + addressable (~> 2.3) + liquid (2.4.1) + maruku (0.6.1) + syntax (>= 1.0.0) + multi_json (1.5.0) + mustache (0.99.4) + rack (1.4.1) + rack-protection (1.3.2) + rack + rdiscount (1.6.8) + ronn (0.7.3) + hpricot (>= 0.8.2) + mustache (>= 0.7.0) + rdiscount (>= 1.5.8) + sass (3.2.3) + sinatra (1.3.3) + rack (~> 1.3, >= 1.3.6) + rack-protection (~> 1.2) + tilt (~> 1.3, >= 1.3.3) + syntax (1.0.0) + tilt (1.3.3) + watch (0.1.0) + +PLATFORMS + ruby + +DEPENDENCIES + bonsai + maruku + ronn diff --git a/docs/Rakefile b/docs/Rakefile index 62b0139e..a95c97fa 100644 --- a/docs/Rakefile +++ b/docs/Rakefile @@ -2,6 +2,8 @@ require 'bonsai' require 'liquid' require 'maruku' require 'json' +require 'ronn' +require 'tempfile' module ExtraFilters def markdownify(input) @@ -38,11 +40,13 @@ task :serve do server = fork { app = Rack::Builder.app { - use Bonsai::StaticPassThrough, :root => Bonsai.root_dir + "/output", :urls => ["/"] + map "/jq" do + use Bonsai::StaticPassThrough, :root => Bonsai.root_dir + "/output", :urls => ["/"] + end run Bonsai::DevelopmentServer } Rack::Handler.default.run(app, :Port => 5000) do - Launchy.open("http://localhost:5000/") + Launchy.open("http://localhost:5000/jq") end } Watch.new("{content,templates,public}/**/*") { Bonsai::Exporter.process! } @@ -57,3 +61,50 @@ task :build do Bonsai.root_dir = Dir.pwd Bonsai::Exporter.publish! end + +def load_manual + YAML::ENGINE.yamler = 'syck' + YAML::load(File.open("content/3.manual/manual.yml")) +end + +task :manpage do + Tempfile.open "manpage" do |f| + manual = load_manual + f.puts manual['manpage_intro'] + f.puts manual['body'] + manual['sections'].each do |section| + + f.puts "## #{section['title'].upcase}\n" + f.puts section['body'] + f.puts "" + (section['entries'] || []).each do |entry| + f.puts "### #{entry['title']}\n" + f.puts entry['body'] + f.puts "" + (entry['examples'] || []).each do |example| + f.puts " jq '#{example['program']}'" + f.puts " #{example['input']}" + f.puts " => #{example['output'].join(", ")}" + f.puts + end + end + f.puts "" + end + f.puts manual['manpage_epilogue'] + f.close + puts Ronn::Document.new(f.path).convert('roff').gsub(/<\/?code>/,"") + end +end + +task :mantests do + load_manual['sections'].each do |section| + (section['entries'] || []).each do |entry| + (entry['examples'] || []).each do |example| + puts example['program'].gsub("\n", " ") + puts example['input'] + example['output'].each do |s| puts s end + puts + end + end + end +end diff --git a/docs/content/2.download/default.yml b/docs/content/2.download/default.yml index 7834ce72..502ef0b4 100644 --- a/docs/content/2.download/default.yml +++ b/docs/content/2.download/default.yml @@ -5,39 +5,46 @@ body: jq is written in C and has no runtime dependencies, so it should be possible to build it for nearly any platform. Prebuilt binaries are - available for Linux (64-bit x86) and OS X. - - * [Download binary for 64-bit Linux](linux_x86_64/jq) - * [Download binary for OS X](osx_64/jq) - (or use [homebrew](http://mxcl.github.com/homebrew/): `brew install jq`) - * [Download source](source/jq.tgz) - - The binaries should just run, but you may need to make them - executable first using: - - chmod +x jq - + available for Linux, OS X and Windows. + + The binaries should just run, but on OS X and Linux you may need + to make them executable first using `chmod +x jq`. + jq is licensed under the MIT license. For all of the gory details, read the file `COPYING` in the source distribution. - Arch Linux - ---------- - A PKGBUILD for jq-1.1 is in the - [AUR](https://aur.archlinux.org/packages.php?ID=63849), as well as a - PKGBUILD for the HEAD of master - ([jq-git](https://aur.archlinux.org/packages.php?ID=63850)). + ### Linux + + * Binaries for [64-bit](linux64/jq) or [32-bit](linux32/jq) systems. + + * For Arch users, a PKGBUILD for jq-1.1 is in the + [AUR](https://aur.archlinux.org/packages.php?ID=63849), as + well as a PKGBUILD for the HEAD of master + ([jq-git](https://aur.archlinux.org/packages.php?ID=63850)). + You can install them using + [Yaourt](https://wiki.archlinux.org/index.php/Yaourt) or + manually by following instructions on [Arch Linux's + Wiki](https://wiki.archlinux.org/index.php/Arch_UseRepository). + + * Debian/Ubuntu packages are coming Real Soon Now. + + ### OS X + + * `brew install jq` using [homebrew](http://mxcl.github.com/homebrew/) - You can install jq using [Yaourt](https://wiki.archlinux.org/index.php/Yaourt) - or manually by following instructions on - [Arch Linux's Wiki](https://wiki.archlinux.org/index.php/Arch_User_Repository). + * Or, grab prebuilt [64-bit binaries](osx64/jq) or [32-bit + binaries](osx32/jq) - Hacking on jq - ============= + ### Windows - If you want to work on jq, grab the source from - [https://github.com/stedolan/jq](https://github.com/stedolan/jq). - + * Executables for [64-bit](win64/jq.exe) or [32-bit](win32/jq.exe) + + ### From source on Linux or OS X + + git clone https://github.com/stedolan/jq.git + cd jq + make && sudo make install To build it from a git clone, you'll need to install a few packages first: @@ -48,23 +55,24 @@ body: * [GCC](http://gcc.gnu.org) * [Make](http://www.gnu.org/software/make) - Most of these aren't necessary if you're just trying to compile - jq from the released tarball - that version has the - non-platform-specific build steps already done, so you'll only - need a C compiler and `make` to finish it off. - For Linux systems, these will all be in your system's package manager, and if you do development on the machine they're most - likely already installed. I have no idea how to get these - installed on OS X, you're on your own there. + likely already installed. + + On OS X, these are all included in Apple's command line tools, which + can be installed from [Xcode](http://developer.apple.com/technologies/tools/). + However, you may find that you need a newer version of Bison than the one provided + by Apple. This can be found in [Homebrew](http://mxcl.github.com/homebrew/) + or [MacPorts](http://macports.org/). `flex` and `bison` are used to generate the lexer and parser for jq, and some python scripts generate the UTF8 encoding tables needed for JSON parsing. - Building the documentation - -- + #### Building the documentation jq's documentation is compiled into static HTML using [Bonsai](http://www.tinytree.info). To view the documentation locally, run `rake serve` from the docs/ subdirectory. + + diff --git a/docs/content/2.download/linux_x86_64/jq b/docs/content/2.download/linux_x86_64/jq Binary files differdeleted file mode 100755 index 4395acc1..00000000 --- a/docs/content/2.download/linux_x86_64/jq +++ /dev/null diff --git a/docs/content/2.download/osx_64/jq b/docs/content/2.download/osx_64/jq Binary files differdeleted file mode 100755 index c7b521ec..00000000 --- a/docs/content/2.download/osx_64/jq +++ /dev/null diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml index 437afdff..de608210 100644 --- a/docs/content/3.manual/manual.yml +++ b/docs/content/3.manual/manual.yml @@ -26,6 +26,41 @@ body: | But that's getting ahead of ourselves. :) Let's start with something simpler: + +manpage_intro: | + jq(1) -- Command-line JSON processor + ==================================== + + ## SYNOPSIS + + `jq` [<options>...] <filter> [<files>...] + + `jq` can transform JSON in various ways, by selecting, iterating, + reducing and otherwise mangling JSON documents. For instance, + running the command `jq 'map(.price) | add'` will take an array of + JSON objects as input and return the sum of their "price" fields. + + By default, `jq` reads a stream of JSON objects (whitespace + separated) from `stdin`. One or more <files> may be specified, in + which case `jq` will read input from those instead. + + The <options> are described in the [INVOKING JQ] section, they + mostly concern input and output formatting. The <filter> is written + in the jq language and specifies how to transform the input + document. + + ## FILTERS + +manpage_epilogue: | + ## BUGS + + Presumably. Report them or discuss them at: + + https://github.com/stedolan/jq/issues + + ## AUTHOR + + Stephen Dolan `<mu@netsoc.tcd.ie>` sections: - title: Invoking jq @@ -40,41 +75,47 @@ sections: You can affect how jq reads and writes its input and output using some command-line options: - * `--slurp`/`-s` - + * `--slurp`/`-s`: + Instead of running the filter for each JSON object in the input, read the entire input stream into a large array and run the filter just once. - * `--raw-input`/`-R` + * `--raw-input`/`-R`: Don't parse the input as JSON. Instead, each line of text is passed to the filter as a string. If combined with `--slurp`, then the entire input is passed to the filter as a single long string. - - * `--null-input`/`-n` - + + * `--null-input`/`-n`: + Don't read any input at all! Instead, the filter is run once using `null` as the input. This is useful when using jq as a simple calculator or to construct JSON data from scratch. - - * `--compact-output` / `-c` - + + * `--compact-output` / `-c`: + By default, jq pretty-prints JSON output. Using this option will result in more compact output by instead putting each JSON object on a single line. - - * `--ascii-output` / `-a` - + + * `--colour-output` / `-C` and `--monochrome-output` / `-M`: + + By default, jq outputs colored JSON if writing to a + terminal. You can force it to produce color even if writing to + a pipe or a file using `-C`, and disable color with `-M`. + + * `--ascii-output` / `-a`: + jq usually outputs non-ASCII Unicode codepoints as UTF-8, even if the input specified them as escape sequences (like "\u03bc"). Using this option, you can force jq to produce pure ASCII output with every non-ASCII character replaced with the equivalent escape sequence. - - * `--raw-output` / `-r` - + + * `--raw-output` / `-r`: + With this option, if the filter's result is a string then it will be written directly to standard output rather than being formatted as a JSON string with quotes. This can be useful for @@ -142,7 +183,7 @@ sections: examples: - program: '.[]' - input: '[{name":"JSON", "good":true}, {"name":"XML", "good":false}]' + input: '[{"name":"JSON", "good":true}, {"name":"XML", "good":false}]' output: - '{"name":"JSON", "good":true}' - '{"name":"XML", "good":false}' @@ -172,7 +213,7 @@ sections: - program: '.[4,2]' input: '["a","b","c","d","e"]' - output: ['"d"', '"c"'] + output: ['"e"', '"c"'] - title: "`|`" body: | @@ -188,7 +229,7 @@ sections: examples: - program: '.[] | .name' - input: '[{name":"JSON", "good":true}, {"name":"XML", "good":false}]' + input: '[{"name":"JSON", "good":true}, {"name":"XML", "good":false}]' output: ['"JSON"', '"XML"'] - title: Types and Values @@ -315,14 +356,23 @@ sections: the key-value pairs from both objects into a single combined object. If both objects contain a value for the same key, the object on the right of the `+` wins. + + `null` can be added to any value, and returns the other + value unchanged. examples: - program: '.a + 1' input: '{"a": 7}' - output: '{"a": 8}' + output: ['8'] - program: '.a + .b' input: '{"a": [1,2], "b": [3,4]}' output: ['[1,2,3,4]'] + - program: '.a + null' + input: '{"a": 1}' + output: ['1'] + - program: '.a + 1' + input: '{}' + output: ['1'] - program: '{a: 1} + {b: 2} + {c: 3} + {a: 42}' input: 'null' output: ['{"a": 42, "b": 2, "c": 3}'] @@ -403,11 +453,11 @@ sections: `foo` returns true for that input, and produces no output otherwise. - It's useful for filtering lists: `[1,2,3] | select(. >= 2)` + It's useful for filtering lists: `[1,2,3] | map(select(. >= 2))` will give you `[3]`. examples: - - program: 'select(. >= 2)' + - program: 'map(select(. >= 2))' input: '[1,5,3,0,7]' output: ['[5,3,7]'] @@ -421,7 +471,7 @@ sections: examples: - program: '1, empty, 2' input: 'null' - output: [1,2] + output: [1, 2] - program: '[1,2,empty,3]' input: 'null' output: ['[1,2,3]'] @@ -455,7 +505,7 @@ sections: examples: - program: add input: '["a","b","c"]' - output: ["abc"] + output: ['"abc"'] - program: add input: '[1, 2, 3]' output: [6] @@ -473,7 +523,7 @@ sections: examples: - program: '.[] | tonumber' input: '[1, "1"]' - output: [1,1] + output: [1, 1] - title: `tostring` body: | @@ -487,6 +537,144 @@ sections: input: '[1, "1", [1]]' output: ['"1"', '"1"', '"[1]"'] + - title: `sort, sort_by` + body: | + + The `sort` functions sorts its input, which must be an + array. Values are sorted in the following order: + + * `null` + * `false` + * `true` + * numbers + * strings, in alphabetical order (by unicode codepoint value) + * arrays, in lexical order + * objects + + The ordering for objects is a little complex: first they're + compared by comparing their sets of keys (as arrays in + sorted order), and if their keys are equal then the values + are compared key by key. + + `sort_by` may be used to sort by a particular field of an + object, or by applying any jq filter. `sort_by(foo)` + compares two elements by comparing the result of `foo` on + each element. + + examples: + - program: 'sort' + input: '[8,3,null,6]' + output: ['[null,3,6,8]'] + - program: 'sort_by(.foo)' + input: '[{"foo":4, "bar":10}, {"foo":3, "bar":100}, {"foo":2, "bar":1}]' + output: ['[{"foo":2, "bar":1}, {"foo":3, "bar":100}, {"foo":4, "bar":10}]'] + + - title: `group_by` + body: | + + `group_by(.foo)` takes as input an array, groups the + elements having the same `.foo` field into separate arrays, + and produces all of these arrays as elements of a larger + array, sorted by the value of the `.foo` field. + + Any jq expression, not just a field access, may be used in + place of `.foo`. The sorting order is the same as described + in the `sort` function above. + + examples: + - program: 'group_by(.foo)' + input: '[{"foo":1, "bar":10}, {"foo":3, "bar":100}, {"foo":1, "bar":1}]' + output: ['[[{"foo":1, "bar":10}, {"foo":1, "bar":1}], [{"foo":3, "bar":100}]]'] + + - title: `min`, `max`, `min_by`, `max_by` + body: | + + Find the minimum or maximum element of the input array. The + `_by` versions allow you to specify a particular field or + property to examine, e.g. `min_by(.foo)` finds the object + with the smallest `foo` field. + + examples: + - program: 'min' + input: '[5,4,2,7]' + output: ['2'] + - program: 'max_by(.foo)' + input: '[{"foo":1, "bar":14}, {"foo":2, "bar":3}]' + output: ['{"foo":2, "bar":3}'] + + - title: `unique` + body: | + + The `unique` function takes as input an array and produces + an array of the same elements, in sorted order, with + duplicates removed. + + examples: + - program: 'unique' + input: '[1,2,5,3,5,3,1,3]' + output: ['[1,2,3,5]'] + + - title: `contains` + body: | + + The filter `contains(b)` will produce true if b is + completely contained within the input. A string B is + contained in a string A if B is a substring of A. An array B + is contained in an array A is all elements in B are + contained in any element in A. An object B is contained in + object A if all of the values in B are contained in the + value in A with the same key. All other types are assumed to + be contained in each other if they are equal. + + examples: + - program: 'contains("bar")' + input: '"foobar"' + output: ['true'] + - program: 'contains(["baz", "bar"])' + input: '["foobar", "foobaz", "blarp"]' + output: ['true'] + - program: 'contains(["bazzzzz", "bar"])' + input: '["foobar", "foobaz", "blarp"]' + output: ['false'] + - program: 'contains({foo: 12, bar: [{barp: 12}]})' + input: '{"foo": 12, "bar":[1,2,{"barp":12, "blip":13}]}' + output: ['true'] + - program: 'contains({foo: 12, bar: [{barp: 15}]})' + input: '{"foo": 12, "bar":[1,2,{"barp":12, "blip":13}]}' + output: ['false'] + + - title: `recurse` + body: | + + The `recurse` function allows you to search through a + recursive structure, and extract interesting data from all + levels. Suppose your input represents a filesystem: + + {"name": "/", "children": [ + {"name": "/bin", "children": [ + {"name": "/bin/ls", "children": []}, + {"name": "/bin/sh", "children": []}]}, + {"name": "/home", "children": [ + {"name": "/home/stephen", "children": [ + {"name": "/home/stephen/jq", "children": []}]}]}]} + + Now suppose you want to extract all of the filenames + present. You need to retrieve `.name`, `.children[].name`, + `.children[].children[].name`, and so on. You can do this + with: + + recurse(.children[]) | .name + + examples: + - program: 'recurse(.foo[])' + input: '{"foo":[{"foo": []}, {"foo":[{"foo":[]}]}]}' + output: + - '{"foo":[{"foo":[]},{"foo":[{"foo":[]}]}]}' + - '{"foo":[]}' + - '{"foo":[{"foo":[]}]}' + - '{"foo":[]}' + + - title: "String interpolation - `\(foo)`" body: | @@ -499,10 +687,77 @@ sections: input: '42' output: ['"The input was 42, which is one less than 43"'] - + - title: "Format strings and escaping" + body: | - + The `@foo` syntax is used to format and escape strings, + which is useful for building URLs, documents in a language + like HTML or XML, and so forth. `@foo` can be used as a + filter on its own, the possible escapings are: + + * `@text`: + + Calls `tostring`, see that function for details. + + * `@json`: + + Serialises the input as JSON. + + * `@html`: + + Applies HTML/XML escaping, by mapping the characters + `<>&'"` to their entity equivalents `<`, `>`, + `&`, `'`, `"`. + + * `@uri`: + + Applies percent-encoding, by mapping all reserved URI + characters to a `%xx` sequence. + + * `@csv`: + + The input must be an array, and it is rendered as CSV + with double quotes for strings, and quotes escaped by + repetition. + + * `@sh`: + + The input is escaped suitable for use in a command-line + for a POSIX shell. If the input is an array, the output + will be a series of space-separated strings. + + * `@base64`: + + The input is converted to base64 as specified by RFC 4648. + + This syntax can be combined with string interpolation in a + useful way. You can follow a `@foo` token with a string + literal. The contents of the string literal will *not* be + escaped. However, all interpolations made inside that string + literal will be escaped. For instance, + @uri "http://www.google.com/search?q=\(.search)" + + will produce the following output for the input + `{"search":"jq!"}`: + + http://www.google.com/search?q=jq%21 + + Note that the slashes, question mark, etc. in the URL are + not escaped, as they were part of the string literal. + + examples: + - program: '@html' + input: '"This works if x < y"' + output: ['"This works if x < y"'] + +# - program: '@html "<span>Anonymous said: \(.)</span>"' +# input: '"<script>alert(\"lol hax\");</script>"' +# output: ["<span>Anonymous said: <script>alert("lol hax");</script></span>"] + + - program: '@sh "echo \(.)"' + input: "\"O'Hara's Ale\"" + output: ["\"echo 'O'\\''Hara'\\''s Ale\""] - title: Conditionals and Comparisons entries: @@ -521,34 +776,7 @@ sections: examples: - program: '.[] == 1' input: '[1, 1.0, "1", "banana"]' - output: ['[true, true, false, false]'] - - title: `contains` - body: | - - The expression 'a contains b' will produce true if b is completely - contained within a. A string B is contained in a string A if B is a - substring of A. An array B is contained in an array A is all elements - in B are contained in any element in A. An object B is contained in - object A if all of the values in B are contained in the value in A with - the same key. All other types are assumed to be contained in each other - if they are equal. - - examples: - - program: '. == contains "bar"' - input: '"foobar"' - output: ['true'] - - program: '. contains ["baz", "bar"]' - input: '["foobar", "foobaz", "blarp"]' - output: ['true'] - - program: '. contains ["bazzzzz", "bar"]' - input: '["foobar", "foobaz", "blarp"]' - output: ['false'] - - program: '. contains {foo: 12, bar: [{barp: 12}]}' - input: '{foo: 12, bar:[1,2,{barp:12, blip:13}]}' - output: ['true'] - - program: '. contains {foo: 12, bar: [{barp: 15}]}' - input: '{foo: 12, bar:[1,2,{barp:12, blip:13}]}' - output: ['false'] + output: ['true', 'true', 'false', 'false'] - title: if-then-else body: | @@ -561,8 +789,8 @@ sections: means that you'll sometimes have to be more explicit about the condition you want: you can't test whether, e.g. a string is empty using `if .name then A else B end`, you'll - need something more like 'if (.name | count) > 0 then A else - B end' instead. + need something more like `if (.name | count) > 0 then A else + B end` instead. If the condition A produces multiple results, it is considered "true" if any of those results is not false or @@ -581,6 +809,21 @@ sections: end input: 2 output: ['"many"'] + + - title: `>, >=, <=, <` + body: | + + The comparison operators `>`, `>=`, `<=`, `<` return whether + their left argument is greater than, greater than or equal + to, less than or equal to or less than their right argument + (respectively). + + The ordering is the same as that described for `sort`, above. + + examples: + - program: '. < 5' + input: 2 + output: ['true'] - title: and/or/not body: | @@ -639,7 +882,7 @@ sections: input: '{}' output: [42] - - title: Variables and Functions + - title: Advanced features body: | Variables are an absolute necessity in most programming languages, but they're relegated to an "advanced feature" in jq. @@ -656,6 +899,10 @@ sections: (many jq functions such as `map` and `find` are in fact written in jq). + Finally, jq has a `fold` operation, which is very powerful but a + bit tricky. Again, it's mostly used internally, to define some + useful bits of jq's standard library. + entries: - title: Variables body: | @@ -670,8 +917,8 @@ sections: For instance, calculating the average value of an array of numbers requires a few variables in most languages - at least one to hold the array, perhaps one for each element or for a loop counter. In jq, it's - simply `add / length` - the `sum` expression is given the array and - produces its sum, and the `count` expression is given the array and + simply `add / length` - the `add` expression is given the array and + produces its sum, and the `length` expression is given the array and produces its length. So, there's generally a cleaner way to solve most problems in jq that @@ -754,12 +1001,45 @@ sections: input's `.foo` field to each element of the array. examples: - - program: 'def addvalue(f): map(. + [$value]); addvalue(.[0])' + - program: 'def addvalue(f): . + [f]; map(addvalue(.[0]))' input: '[[1,2],[10,20]]' output: ['[[1,2,1], [10,20,10]]'] - - program: 'def addvalue(f): f as $x | map (. + $x); addvalue(.[0])' + - program: 'def addvalue(f): f as $x | map(. + $x); addvalue(.[0])' input: '[[1,2],[10,20]]' - output: ['[[1,2,[1,2]], [10,20,[1,2]]]'] + output: ['[[1,2,1,2], [10,20,1,2]]'] + + - title: Fold + body: | + + The `fold` syntax in jq allows you to combine all of the + results of an expression by accumulating them into a single + answer. As an example, we'll pass `[3,2,1]` to this expression: + + fold 0 as $sum (.[] | $sum + .) + + The variable `$sum` is first given the value `0`. The body + of the fold (i.e. `.[] | $sum + .`) is evaluated. `.[]` + produces three results, `3`, `2`, and `1`. For the first + one, `$sum + .` gives `3`. + + Having produced this answer, jq backtracks to find the next + result as per usual. However, this time, `$sum` is set to + the previous value of the body, so `$sum + .` gives + `5`. After the final backtracking, `$sum + .` gives + `6`. This final value is used as the value of the entire + `fold` expression, so the above filter returns `6`. + + More formally, in order to evaluate `fold INIT as $VAR + (BODY)`, jq first sets `$VAR` to the value of `INIT`. It + then runs through `BODY`. Each time `BODY` produces a value, + `$VAR` is set to that value and jq backtracks to find the + next one. When `BODY` stops producing values, the final + value of `$VAR` is the result of the entire expression. + + examples: + - program: 'fold 0 as $sum (.[] | $sum + .)' + input: '[10,2,5,3]' + output: ['20'] - title: Assignment @@ -871,4 +1151,5 @@ sections: "stedolan" wrote, and we can comment on each of them in the same way that we did before: - (.posts[] | select(.author == "stedolan") | .comments) |= . + ["terrible."] + (.posts[] | select(.author == "stedolan") | .comments) |= + . + ["terrible."] diff --git a/docs/site.yml b/docs/site.yml index 92a690d1..863d578d 100644 --- a/docs/site.yml +++ b/docs/site.yml @@ -1,10 +1,8 @@ # The key value pairs found below are available within the templates. -jq_version: 1.1 -# Next line is needed for publishing to github pages +jq_version: 1.2 root: '/jq' -# root: '' footer: | This website is made with [Bonsai](http://www.tinytree.info) and diff --git a/docs/templates/index.liquid b/docs/templates/index.liquid index aaff1c9f..7785526c 100644 --- a/docs/templates/index.liquid +++ b/docs/templates/index.liquid @@ -16,8 +16,8 @@ <span class="caret"></span> </a> <ul class="dropdown-menu"> - <li><a href="{{root}}/download/linux_x86_64/jq">Linux (x86_64)</a></li> - <li><a href="{{root}}/download/osx_64/jq">OS X (64-bit)</a></li> + <li><a href="{{root}}/download/linux64/jq">Linux (64-bit)</a></li> + <li><a href="{{root}}/download/osx64/jq">OS X (64-bit)</a></li> <li><a href="{{root}}/download">Other platforms and source</a></li> </ul> </div> |