Add a bunch of commandline options for controlling I/O format.
Also docs for the above. Closes #1.
This commit is contained in:
1 parent
fcd7cf4ddd
commit
359d5f33bd
2 files changed
+190
-30
No files matched your search
@@ -28,7 +28,59 @@ body: |
|
|||||||
simpler:
|
simpler:
|
||||||
|
|
||||||
sections:
|
sections:
|
||||||
- title: Basics
|
- title: Invoking jq
|
||||||
|
body: |
|
||||||
|
|
||||||
|
jq filters run on a stream of JSON data. The input to jq is
|
||||||
|
parsed as a sequence of whitespace-separated JSON values which
|
||||||
|
are passed through the provided filter one at a time. The
|
||||||
|
output(s) of the filter are written to standard out, again as a
|
||||||
|
sequence of whitespace-separated JSON data.
|
||||||
|
|
||||||
|
You can affect how jq reads and writes its input and output
|
||||||
|
using some command-line options:
|
||||||
|
|
||||||
|
* `--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`
|
||||||
|
|
||||||
|
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`
|
||||||
|
|
||||||
|
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`
|
||||||
|
|
||||||
|
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`
|
||||||
|
|
||||||
|
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`
|
||||||
|
|
||||||
|
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
|
||||||
|
making jq filters talk to non-JSON-based systems.
|
||||||
|
|
||||||
|
- title: Basic filters
|
||||||
entries:
|
entries:
|
||||||
- title: "`.`"
|
- title: "`.`"
|
||||||
body: |
|
body: |
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include "compile.h"
|
#include "compile.h"
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
#include "jv.h"
|
#include "jv.h"
|
||||||
@@ -12,17 +13,98 @@ static const char* progname;
|
|||||||
|
|
||||||
static void usage() {
|
static void usage() {
|
||||||
fprintf(stderr, "\njq - commandline JSON processor\n");
|
fprintf(stderr, "\njq - commandline JSON processor\n");
|
||||||
fprintf(stderr, "Usage: %s <jq filter>\n\n", progname);
|
fprintf(stderr, "Usage: %s [options] <jq filter>\n\n", progname);
|
||||||
fprintf(stderr, "For a description of how to write jq filters and\n");
|
fprintf(stderr, "For a description of the command line options and\n");
|
||||||
fprintf(stderr, "why you might want to, see the jq documentation at\n");
|
fprintf(stderr, "how to write jq filters (and why you might want to)\n");
|
||||||
fprintf(stderr, "http://stedolan.github.com/jq\n\n");
|
fprintf(stderr, "see the jq documentation at http://stedolan.github.com/jq\n\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void die() {
|
||||||
|
fprintf(stderr, "Use %s --help for help with command-line options,\n", progname);
|
||||||
|
fprintf(stderr, "or see the jq documentation at http://stedolan.github.com/jq\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int isoptish(const char* text) {
|
||||||
|
return text[0] == '-' && (text[1] == '-' || isalpha(text[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isoption(const char* text, char shortopt, const char* longopt) {
|
||||||
|
if (text[0] != '-') return 0;
|
||||||
|
if (strlen(text) == 2 && text[1] == shortopt) return 1;
|
||||||
|
if (text[1] == '-' && !strcmp(text+2, longopt)) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SLURP = 1,
|
||||||
|
RAW_INPUT = 2,
|
||||||
|
PROVIDE_NULL = 4,
|
||||||
|
|
||||||
|
RAW_OUTPUT = 8,
|
||||||
|
COMPACT_OUTPUT = 16,
|
||||||
|
ASCII_OUTPUT = 32,
|
||||||
|
};
|
||||||
|
static int options = 0;
|
||||||
|
static struct bytecode* bc;
|
||||||
|
|
||||||
|
static void process(jv value) {
|
||||||
|
jq_init(bc, value);
|
||||||
|
jv result;
|
||||||
|
while (jv_is_valid(result = jq_next())) {
|
||||||
|
if ((options & RAW_OUTPUT) && jv_get_kind(result) == JV_KIND_STRING) {
|
||||||
|
fwrite(jv_string_value(result), 1, jv_string_length(jv_copy(result)), stdout);
|
||||||
|
} else {
|
||||||
|
int dumpopts = 0;
|
||||||
|
if (!(options & COMPACT_OUTPUT)) dumpopts |= JV_PRINT_PRETTY;
|
||||||
|
if (options & ASCII_OUTPUT) dumpopts |= JV_PRINT_ASCII;
|
||||||
|
jv_dump(result, dumpopts);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
jv_free(result);
|
||||||
|
jq_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if (argc) progname = argv[0];
|
if (argc) progname = argv[0];
|
||||||
if (argc != 2 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "--version")) usage();
|
|
||||||
struct bytecode* bc = jq_compile(argv[1]);
|
const char* program = 0;
|
||||||
|
for (int i=1; i<argc; i++) {
|
||||||
|
if (!isoptish(argv[i])) {
|
||||||
|
if (program) usage();
|
||||||
|
program = argv[i];
|
||||||
|
} else if (isoption(argv[i], 's', "slurp")) {
|
||||||
|
options |= SLURP;
|
||||||
|
} else if (isoption(argv[i], 'r', "raw-output")) {
|
||||||
|
options |= RAW_OUTPUT;
|
||||||
|
} else if (isoption(argv[i], 'c', "compact-output")) {
|
||||||
|
options |= COMPACT_OUTPUT;
|
||||||
|
} else if (isoption(argv[i], 'a', "ascii-output")) {
|
||||||
|
options |= ASCII_OUTPUT;
|
||||||
|
} else if (isoption(argv[i], 'R', "raw-input")) {
|
||||||
|
options |= RAW_INPUT;
|
||||||
|
} else if (isoption(argv[i], 'n', "null-input")) {
|
||||||
|
options |= PROVIDE_NULL;
|
||||||
|
} else if (isoption(argv[i], 'h', "help")) {
|
||||||
|
usage();
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s: Unknown option %s\n", progname, argv[i]);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!program) usage();
|
||||||
|
|
||||||
|
if ((options & PROVIDE_NULL) && (options & (RAW_INPUT | SLURP))) {
|
||||||
|
fprintf(stderr, "%s: --null-input cannot be used with --raw-input or --slurp\n", program);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
bc = jq_compile(program);
|
||||||
if (!bc) return 1;
|
if (!bc) return 1;
|
||||||
|
|
||||||
#if JQ_DEBUG
|
#if JQ_DEBUG
|
||||||
@@ -30,33 +112,59 @@ int main(int argc, char* argv[]) {
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct jv_parser parser;
|
if (options & PROVIDE_NULL) {
|
||||||
jv_parser_init(&parser);
|
process(jv_null());
|
||||||
while (!feof(stdin)) {
|
} else {
|
||||||
char buf[4096];
|
jv slurped;
|
||||||
if (!fgets(buf, sizeof(buf), stdin)) buf[0] = 0;
|
if (options & SLURP) slurped = jv_invalid();
|
||||||
jv_parser_set_buf(&parser, buf, strlen(buf), !feof(stdin));
|
int first = 1;
|
||||||
jv value;
|
struct jv_parser parser;
|
||||||
while (jv_is_valid((value = jv_parser_next(&parser)))) {
|
jv_parser_init(&parser);
|
||||||
jq_init(bc, value);
|
while (!feof(stdin)) {
|
||||||
jv result;
|
char buf[4096];
|
||||||
while (jv_is_valid(result = jq_next())) {
|
if (!fgets(buf, sizeof(buf), stdin)) buf[0] = 0;
|
||||||
jv_dump(result, JV_PRINT_PRETTY);
|
if (options & RAW_INPUT) {
|
||||||
printf("\n");
|
int len = strlen(buf);
|
||||||
|
if (len > 0) {
|
||||||
|
if (options & SLURP) {
|
||||||
|
if (first) slurped = jv_string(buf);
|
||||||
|
else slurped = jv_string_concat(slurped, jv_string(buf));
|
||||||
|
} else {
|
||||||
|
if (buf[len-1] == '\n') buf[len-1] = 0;
|
||||||
|
process(jv_string(buf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
jv_parser_set_buf(&parser, buf, strlen(buf), !feof(stdin));
|
||||||
|
jv value;
|
||||||
|
while (jv_is_valid((value = jv_parser_next(&parser)))) {
|
||||||
|
if (options & SLURP) {
|
||||||
|
if (first) slurped = jv_array();
|
||||||
|
slurped = jv_array_append(slurped, value);
|
||||||
|
} else {
|
||||||
|
process(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (jv_invalid_has_msg(jv_copy(value))) {
|
||||||
|
jv msg = jv_invalid_get_msg(value);
|
||||||
|
fprintf(stderr, "parse error: %s\n", jv_string_value(msg));
|
||||||
|
jv_free(msg);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
jv_free(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
jv_free(result);
|
first = 0;
|
||||||
jq_teardown();
|
|
||||||
}
|
}
|
||||||
if (jv_invalid_has_msg(jv_copy(value))) {
|
jv_parser_free(&parser);
|
||||||
jv msg = jv_invalid_get_msg(value);
|
if (options & SLURP) {
|
||||||
fprintf(stderr, "parse error: %s\n", jv_string_value(msg));
|
if (jv_is_valid(slurped)) {
|
||||||
jv_free(msg);
|
process(slurped);
|
||||||
break;
|
} else {
|
||||||
} else {
|
jv_free(slurped);
|
||||||
jv_free(value);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jv_parser_free(&parser);
|
|
||||||
|
|
||||||
bytecode_free(bc);
|
bytecode_free(bc);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in new issue
Block a user