#include "lib/mlr_globals.h" #include "lib/mlrutil.h" #include "containers/hss.h" #include "mlr_dsl_cst.h" #include "context_flags.h" // ---------------------------------------------------------------- typedef void keyword_usage_func_t(FILE* ostream); static keyword_usage_func_t mlr_dsl_ENV_keyword_usage; static keyword_usage_func_t mlr_dsl_FILENAME_keyword_usage; static keyword_usage_func_t mlr_dsl_FILENUM_keyword_usage; static keyword_usage_func_t mlr_dsl_FNR_keyword_usage; static keyword_usage_func_t mlr_dsl_IFS_keyword_usage; static keyword_usage_func_t mlr_dsl_IPS_keyword_usage; static keyword_usage_func_t mlr_dsl_IRS_keyword_usage; static keyword_usage_func_t mlr_dsl_M_E_keyword_usage; static keyword_usage_func_t mlr_dsl_M_PI_keyword_usage; static keyword_usage_func_t mlr_dsl_NF_keyword_usage; static keyword_usage_func_t mlr_dsl_NR_keyword_usage; static keyword_usage_func_t mlr_dsl_OFS_keyword_usage; static keyword_usage_func_t mlr_dsl_OPS_keyword_usage; static keyword_usage_func_t mlr_dsl_ORS_keyword_usage; static keyword_usage_func_t mlr_dsl_all_keyword_usage; static keyword_usage_func_t mlr_dsl_begin_keyword_usage; static keyword_usage_func_t mlr_dsl_bool_keyword_usage; static keyword_usage_func_t mlr_dsl_break_keyword_usage; static keyword_usage_func_t mlr_dsl_call_keyword_usage; static keyword_usage_func_t mlr_dsl_continue_keyword_usage; static keyword_usage_func_t mlr_dsl_do_keyword_usage; static keyword_usage_func_t mlr_dsl_dump_keyword_usage; static keyword_usage_func_t mlr_dsl_edump_keyword_usage; static keyword_usage_func_t mlr_dsl_elif_keyword_usage; static keyword_usage_func_t mlr_dsl_else_keyword_usage; static keyword_usage_func_t mlr_dsl_emit_keyword_usage; static keyword_usage_func_t mlr_dsl_emitf_keyword_usage; static keyword_usage_func_t mlr_dsl_emitp_keyword_usage; static keyword_usage_func_t mlr_dsl_end_keyword_usage; static keyword_usage_func_t mlr_dsl_eprint_keyword_usage; static keyword_usage_func_t mlr_dsl_eprintn_keyword_usage; static keyword_usage_func_t mlr_dsl_false_keyword_usage; static keyword_usage_func_t mlr_dsl_filter_keyword_usage; static keyword_usage_func_t mlr_dsl_float_keyword_usage; static keyword_usage_func_t mlr_dsl_for_keyword_usage; static keyword_usage_func_t mlr_dsl_func_keyword_usage; static keyword_usage_func_t mlr_dsl_if_keyword_usage; static keyword_usage_func_t mlr_dsl_in_keyword_usage; static keyword_usage_func_t mlr_dsl_int_keyword_usage; static keyword_usage_func_t mlr_dsl_map_keyword_usage; static keyword_usage_func_t mlr_dsl_num_keyword_usage; static keyword_usage_func_t mlr_dsl_print_keyword_usage; static keyword_usage_func_t mlr_dsl_printn_keyword_usage; static keyword_usage_func_t mlr_dsl_return_keyword_usage; static keyword_usage_func_t mlr_dsl_stderr_keyword_usage; static keyword_usage_func_t mlr_dsl_stdout_keyword_usage; static keyword_usage_func_t mlr_dsl_str_keyword_usage; static keyword_usage_func_t mlr_dsl_subr_keyword_usage; static keyword_usage_func_t mlr_dsl_tee_keyword_usage; static keyword_usage_func_t mlr_dsl_true_keyword_usage; static keyword_usage_func_t mlr_dsl_unset_keyword_usage; static keyword_usage_func_t mlr_dsl_var_keyword_usage; static keyword_usage_func_t mlr_dsl_while_keyword_usage; // ---------------------------------------------------------------- typedef struct _keyword_usage_entry_t { char* name; keyword_usage_func_t* pusage_func; } keyword_usage_entry_t; static keyword_usage_entry_t KEYWORD_USAGE_TABLE[] = { { "all", mlr_dsl_all_keyword_usage }, { "begin", mlr_dsl_begin_keyword_usage }, { "bool", mlr_dsl_bool_keyword_usage }, { "break", mlr_dsl_break_keyword_usage }, { "call", mlr_dsl_call_keyword_usage }, { "continue", mlr_dsl_continue_keyword_usage }, { "do", mlr_dsl_do_keyword_usage }, { "dump", mlr_dsl_dump_keyword_usage }, { "edump", mlr_dsl_edump_keyword_usage }, { "elif", mlr_dsl_elif_keyword_usage }, { "else", mlr_dsl_else_keyword_usage }, { "emit", mlr_dsl_emit_keyword_usage }, { "emitf", mlr_dsl_emitf_keyword_usage }, { "emitp", mlr_dsl_emitp_keyword_usage }, { "end", mlr_dsl_end_keyword_usage }, { "eprint", mlr_dsl_eprint_keyword_usage }, { "eprintn", mlr_dsl_eprintn_keyword_usage }, { "false", mlr_dsl_false_keyword_usage }, { "filter", mlr_dsl_filter_keyword_usage }, { "float", mlr_dsl_float_keyword_usage }, { "for", mlr_dsl_for_keyword_usage }, { "func", mlr_dsl_func_keyword_usage }, { "if", mlr_dsl_if_keyword_usage }, { "in", mlr_dsl_in_keyword_usage }, { "int", mlr_dsl_int_keyword_usage }, { "map", mlr_dsl_map_keyword_usage }, { "num", mlr_dsl_num_keyword_usage }, { "print", mlr_dsl_print_keyword_usage }, { "printn", mlr_dsl_printn_keyword_usage }, { "return", mlr_dsl_return_keyword_usage }, { "stderr", mlr_dsl_stderr_keyword_usage }, { "stdout", mlr_dsl_stdout_keyword_usage }, { "str", mlr_dsl_str_keyword_usage }, { "subr", mlr_dsl_subr_keyword_usage }, { "tee", mlr_dsl_tee_keyword_usage }, { "true", mlr_dsl_true_keyword_usage }, { "unset", mlr_dsl_unset_keyword_usage }, { "var", mlr_dsl_var_keyword_usage }, { "while", mlr_dsl_while_keyword_usage }, { "ENV", mlr_dsl_ENV_keyword_usage }, { "FILENAME", mlr_dsl_FILENAME_keyword_usage }, { "FILENUM", mlr_dsl_FILENUM_keyword_usage }, { "FNR", mlr_dsl_FNR_keyword_usage }, { "IFS", mlr_dsl_IFS_keyword_usage }, { "IPS", mlr_dsl_IPS_keyword_usage }, { "IRS", mlr_dsl_IRS_keyword_usage }, { "M_E", mlr_dsl_M_E_keyword_usage }, { "M_PI", mlr_dsl_M_PI_keyword_usage }, { "NF", mlr_dsl_NF_keyword_usage }, { "NR", mlr_dsl_NR_keyword_usage }, { "OFS", mlr_dsl_OFS_keyword_usage }, { "OPS", mlr_dsl_OPS_keyword_usage }, { "ORS", mlr_dsl_ORS_keyword_usage }, }; static int KEYWORD_USAGE_TABLE_SIZE = sizeof(KEYWORD_USAGE_TABLE)/sizeof(KEYWORD_USAGE_TABLE[0]); // ================================================================ // Pass function_name == NULL to get usage for all keywords. // Note keywords are defined in parsing/mlr_dsl_lexer.l. void mlr_dsl_keyword_usage(FILE* ostream, char* keyword) { if (keyword == NULL) { for (int i = 0; i < KEYWORD_USAGE_TABLE_SIZE; i++) { if (i > 0) { fprintf(ostream, "\n"); } KEYWORD_USAGE_TABLE[i].pusage_func(ostream); } } else { int found = FALSE; for (int i = 0; i < KEYWORD_USAGE_TABLE_SIZE; i++) { if (streq(keyword, KEYWORD_USAGE_TABLE[i].name)) { KEYWORD_USAGE_TABLE[i].pusage_func(ostream); found = TRUE; break; } } if (!found) { fprintf(ostream, "%s: unrecognized keyword \"%s\".\n", MLR_GLOBALS.bargv0, keyword); } } } void mlr_dsl_list_all_keywords_raw(FILE* ostream) { for (int i = 0; i < KEYWORD_USAGE_TABLE_SIZE; i++) { printf("%s\n", KEYWORD_USAGE_TABLE[i].name); } } // ---------------------------------------------------------------- static void mlr_dsl_all_keyword_usage(FILE* ostream) { fprintf(ostream, "all: used in \"emit\", \"emitp\", and \"unset\" as a synonym for @*\n" ); } static void mlr_dsl_begin_keyword_usage(FILE* ostream) { fprintf(ostream, "begin: defines a block of statements to be executed before input records\n" "are ingested. The body statements must be wrapped in curly braces.\n" "Example: 'begin { @count = 0 }'\n" ); } static void mlr_dsl_bool_keyword_usage(FILE* ostream) { fprintf(ostream, "bool: declares a boolean local variable in the current curly-braced scope.\n" "Type-checking happens at assignment: 'bool b = 1' is an error.\n" ); } static void mlr_dsl_break_keyword_usage(FILE* ostream) { fprintf(ostream, "break: causes execution to continue after the body of the current\n" "for/while/do-while loop.\n" ); } static void mlr_dsl_call_keyword_usage(FILE* ostream) { fprintf(ostream, "call: used for invoking a user-defined subroutine.\n" "Example: 'subr s(k,v) { print k . \" is \" . v} call s(\"a\", $a)'\n" ); } static void mlr_dsl_continue_keyword_usage(FILE* ostream) { fprintf(ostream, "continue: causes execution to skip the remaining statements in the body of\n" "the current for/while/do-while loop. For-loop increments are still applied.\n" ); } static void mlr_dsl_do_keyword_usage(FILE* ostream) { fprintf(ostream, "do: with \"while\", introduces a do-while loop. The body statements must be wrapped\n" "in curly braces.\n" ); } static void mlr_dsl_dump_keyword_usage(FILE* ostream) { fprintf(ostream, "dump: prints all currently defined out-of-stream variables immediately\n" " to stdout as JSON.\n" "\n" " With >, >>, or |, the data do not become part of the output record stream but\n" " are instead redirected.\n" "\n" " The > and >> are for write and append, as in the shell, but (as with awk) the\n" " file-overwrite for > is on first write, not per record. The | is for piping to\n" " a process which will process the data. There will be one open file for each\n" " distinct file name (for > and >>) or one subordinate process for each distinct\n" " value of the piped-to command (for |). Output-formatting flags are taken from\n" " the main command line.\n" "\n" " Example: mlr --from f.dat put -q '@v[NR]=$*; end { dump }'\n" " Example: mlr --from f.dat put -q '@v[NR]=$*; end { dump > \"mytap.dat\"}'\n" " Example: mlr --from f.dat put -q '@v[NR]=$*; end { dump >> \"mytap.dat\"}'\n" " Example: mlr --from f.dat put -q '@v[NR]=$*; end { dump | \"jq .[]\"}'\n"); } static void mlr_dsl_edump_keyword_usage(FILE* ostream) { fprintf(ostream, "edump: prints all currently defined out-of-stream variables immediately\n" " to stderr as JSON.\n" "\n" " Example: mlr --from f.dat put -q '@v[NR]=$*; end { edump }'\n"); } static void mlr_dsl_elif_keyword_usage(FILE* ostream) { fprintf(ostream, "elif: the way Miller spells \"else if\". The body statements must be wrapped\n" "in curly braces.\n" ); } static void mlr_dsl_else_keyword_usage(FILE* ostream) { fprintf(ostream, "else: terminates an if/elif/elif chain. The body statements must be wrapped\n" "in curly braces.\n" ); } static void mlr_dsl_emit_keyword_usage(FILE* ostream) { fprintf(ostream, "emit: inserts an out-of-stream variable into the output record stream. Hashmap\n" " indices present in the data but not slotted by emit arguments are not output.\n" "\n" " With >, >>, or |, the data do not become part of the output record stream but\n" " are instead redirected.\n" "\n" " The > and >> are for write and append, as in the shell, but (as with awk) the\n" " file-overwrite for > is on first write, not per record. The | is for piping to\n" " a process which will process the data. There will be one open file for each\n" " distinct file name (for > and >>) or one subordinate process for each distinct\n" " value of the piped-to command (for |). Output-formatting flags are taken from\n" " the main command line.\n" "\n" " You can use any of the output-format command-line flags, e.g. --ocsv, --ofs,\n" " etc., to control the format of the output if the output is redirected. See also %s -h.\n" "\n" " Example: mlr --from f.dat put 'emit > \"/tmp/data-\".$a, $*'\n" " Example: mlr --from f.dat put 'emit > \"/tmp/data-\".$a, mapexcept($*, \"a\")'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emit @sums'\n" " Example: mlr --from f.dat put --ojson '@sums[$a][$b]+=$x; emit > \"tap-\".$a.$b.\".dat\", @sums'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emit @sums, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emit @*, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emit > \"mytap.dat\", @*, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emit >> \"mytap.dat\", @*, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emit | \"gzip > mytap.dat.gz\", @*, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emit > stderr, @*, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emit | \"grep somepattern\", @*, \"index1\", \"index2\"'\n" "\n" " Please see http://johnkerl.org/miller/doc for more information.\n", MLR_GLOBALS.bargv0); } static void mlr_dsl_emitf_keyword_usage(FILE* ostream) { fprintf(ostream, "emitf: inserts non-indexed out-of-stream variable(s) side-by-side into the\n" " output record stream.\n" "\n" " With >, >>, or |, the data do not become part of the output record stream but\n" " are instead redirected.\n" "\n" " The > and >> are for write and append, as in the shell, but (as with awk) the\n" " file-overwrite for > is on first write, not per record. The | is for piping to\n" " a process which will process the data. There will be one open file for each\n" " distinct file name (for > and >>) or one subordinate process for each distinct\n" " value of the piped-to command (for |). Output-formatting flags are taken from\n" " the main command line.\n" "\n" " You can use any of the output-format command-line flags, e.g. --ocsv, --ofs,\n" " etc., to control the format of the output if the output is redirected. See also %s -h.\n" "\n" " Example: mlr --from f.dat put '@a=$i;@b+=$x;@c+=$y; emitf @a'\n" " Example: mlr --from f.dat put --oxtab '@a=$i;@b+=$x;@c+=$y; emitf > \"tap-\".$i.\".dat\", @a'\n" " Example: mlr --from f.dat put '@a=$i;@b+=$x;@c+=$y; emitf @a, @b, @c'\n" " Example: mlr --from f.dat put '@a=$i;@b+=$x;@c+=$y; emitf > \"mytap.dat\", @a, @b, @c'\n" " Example: mlr --from f.dat put '@a=$i;@b+=$x;@c+=$y; emitf >> \"mytap.dat\", @a, @b, @c'\n" " Example: mlr --from f.dat put '@a=$i;@b+=$x;@c+=$y; emitf > stderr, @a, @b, @c'\n" " Example: mlr --from f.dat put '@a=$i;@b+=$x;@c+=$y; emitf | \"grep somepattern\", @a, @b, @c'\n" " Example: mlr --from f.dat put '@a=$i;@b+=$x;@c+=$y; emitf | \"grep somepattern > mytap.dat\", @a, @b, @c'\n" "\n" " Please see http://johnkerl.org/miller/doc for more information.\n", MLR_GLOBALS.bargv0); } static void mlr_dsl_emitp_keyword_usage(FILE* ostream) { fprintf(ostream, "emitp: inserts an out-of-stream variable into the output record stream.\n" " Hashmap indices present in the data but not slotted by emitp arguments are\n" " output concatenated with \":\".\n" "\n" " With >, >>, or |, the data do not become part of the output record stream but\n" " are instead redirected.\n" "\n" " The > and >> are for write and append, as in the shell, but (as with awk) the\n" " file-overwrite for > is on first write, not per record. The | is for piping to\n" " a process which will process the data. There will be one open file for each\n" " distinct file name (for > and >>) or one subordinate process for each distinct\n" " value of the piped-to command (for |). Output-formatting flags are taken from\n" " the main command line.\n" "\n" " You can use any of the output-format command-line flags, e.g. --ocsv, --ofs,\n" " etc., to control the format of the output if the output is redirected. See also %s -h.\n" "\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emitp @sums'\n" " Example: mlr --from f.dat put --opprint '@sums[$a][$b]+=$x; emitp > \"tap-\".$a.$b.\".dat\", @sums'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emitp @sums, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emitp @*, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emitp > \"mytap.dat\", @*, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emitp >> \"mytap.dat\", @*, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emitp | \"gzip > mytap.dat.gz\", @*, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emitp > stderr, @*, \"index1\", \"index2\"'\n" " Example: mlr --from f.dat put '@sums[$a][$b]+=$x; emitp | \"grep somepattern\", @*, \"index1\", \"index2\"'\n" "\n" " Please see http://johnkerl.org/miller/doc for more information.\n", MLR_GLOBALS.bargv0); } static void mlr_dsl_end_keyword_usage(FILE* ostream) { fprintf(ostream, "end: defines a block of statements to be executed after input records\n" "are ingested. The body statements must be wrapped in curly braces.\n" "Example: 'end { emit @count }'\n" "Example: 'end { eprint \"Final count is \" . @count }'\n" ); } static void mlr_dsl_eprint_keyword_usage(FILE* ostream) { fprintf(ostream, "eprint: prints expression immediately to stderr.\n" " Example: mlr --from f.dat put -q 'eprint \"The sum of x and y is \".($x+$y)'\n" " Example: mlr --from f.dat put -q 'for (k, v in $*) { eprint k . \" => \" . v }'\n" " Example: mlr --from f.dat put '(NR %% 1000 == 0) { eprint \"Checkpoint \".NR}'\n"); } static void mlr_dsl_eprintn_keyword_usage(FILE* ostream) { fprintf(ostream, "eprintn: prints expression immediately to stderr, without trailing newline.\n" " Example: mlr --from f.dat put -q 'eprintn \"The sum of x and y is \".($x+$y); eprint \"\"'\n"); } static void mlr_dsl_false_keyword_usage(FILE* ostream) { fprintf(ostream, "false: the boolean literal value.\n" ); } static void mlr_dsl_filter_keyword_usage(FILE* ostream) { fprintf(ostream, "filter: includes/excludes the record in the output record stream.\n" "\n" " Example: mlr --from f.dat put 'filter (NR == 2 || $x > 5.4)'\n" "\n" " Instead of put with 'filter false' you can simply use put -q. The following\n" " uses the input record to accumulate data but only prints the running sum\n" " without printing the input record:\n" "\n" " Example: mlr --from f.dat put -q '@running_sum += $x * $y; emit @running_sum'\n"); } static void mlr_dsl_float_keyword_usage(FILE* ostream) { fprintf(ostream, "float: declares a floating-point local variable in the current curly-braced scope.\n" "Type-checking happens at assignment: 'float x = 0' is an error.\n" ); } static void mlr_dsl_for_keyword_usage(FILE* ostream) { fprintf(ostream, "for: defines a for-loop using one of three styles. The body statements must\n" "be wrapped in curly braces.\n" "For-loop over stream record:\n" " Example: 'for (k, v in $*) { ... }'\n" "For-loop over out-of-stream variables:\n" " Example: 'for (k, v in @counts) { ... }'\n" " Example: 'for ((k1, k2), v in @counts) { ... }'\n" " Example: 'for ((k1, k2, k3), v in @*) { ... }'\n" "C-style for-loop:\n" " Example: 'for (var i = 0, var b = 1; i < 10; i += 1, b *= 2) { ... }'\n" ); } static void mlr_dsl_func_keyword_usage(FILE* ostream) { fprintf(ostream, "func: used for defining a user-defined function.\n" "Example: 'func f(a,b) { return sqrt(a**2+b**2)} $d = f($x, $y)'\n" ); } static void mlr_dsl_if_keyword_usage(FILE* ostream) { fprintf(ostream, "if: starts an if/elif/elif chain. The body statements must be wrapped\n" "in curly braces.\n" ); } static void mlr_dsl_in_keyword_usage(FILE* ostream) { fprintf(ostream, "in: used in for-loops over stream records or out-of-stream variables.\n"); } static void mlr_dsl_int_keyword_usage(FILE* ostream) { fprintf(ostream, "int: declares an integer local variable in the current curly-braced scope.\n" "Type-checking happens at assignment: 'int x = 0.0' is an error.\n" ); } static void mlr_dsl_map_keyword_usage(FILE* ostream) { fprintf(ostream, "map: declares an map-valued local variable in the current curly-braced scope.\n" "Type-checking happens at assignment: 'map b = 0' is an error. map b = {} is\n" "always OK. map b = a is OK or not depending on whether a is a map.\n" ); } static void mlr_dsl_num_keyword_usage(FILE* ostream) { fprintf(ostream, "num: declares an int/float local variable in the current curly-braced scope.\n" "Type-checking happens at assignment: 'num b = true' is an error.\n" ); } static void mlr_dsl_print_keyword_usage(FILE* ostream) { fprintf(ostream, "print: prints expression immediately to stdout.\n" " Example: mlr --from f.dat put -q 'print \"The sum of x and y is \".($x+$y)'\n" " Example: mlr --from f.dat put -q 'for (k, v in $*) { print k . \" => \" . v }'\n" " Example: mlr --from f.dat put '(NR %% 1000 == 0) { print > stderr, \"Checkpoint \".NR}'\n"); } static void mlr_dsl_printn_keyword_usage(FILE* ostream) { fprintf(ostream, "printn: prints expression immediately to stdout, without trailing newline.\n" " Example: mlr --from f.dat put -q 'printn \".\"; end { print \"\" }'\n"); } static void mlr_dsl_return_keyword_usage(FILE* ostream) { fprintf(ostream, "return: specifies the return value from a user-defined function.\n" "Omitted return statements (including via if-branches) result in an absent-null\n" "return value, which in turns results in a skipped assignment to an LHS.\n" ); } static void mlr_dsl_stderr_keyword_usage(FILE* ostream) { fprintf(ostream, "stderr: Used for tee, emit, emitf, emitp, print, and dump in place of filename\n" " to print to standard error.\n"); } static void mlr_dsl_stdout_keyword_usage(FILE* ostream) { fprintf(ostream, "stdout: Used for tee, emit, emitf, emitp, print, and dump in place of filename\n" " to print to standard output.\n"); } static void mlr_dsl_str_keyword_usage(FILE* ostream) { fprintf(ostream, "str: declares a string local variable in the current curly-braced scope.\n" "Type-checking happens at assignment.\n" ); } static void mlr_dsl_subr_keyword_usage(FILE* ostream) { fprintf(ostream, "subr: used for defining a subroutine.\n" "Example: 'subr s(k,v) { print k . \" is \" . v} call s(\"a\", $a)'\n" ); } static void mlr_dsl_tee_keyword_usage(FILE* ostream) { fprintf(ostream, "tee: prints the current record to specified file.\n" " This is an immediate print to the specified file (except for pprint format\n" " which of course waits until the end of the input stream to format all output).\n" "\n" " The > and >> are for write and append, as in the shell, but (as with awk) the\n" " file-overwrite for > is on first write, not per record. The | is for piping to\n" " a process which will process the data. There will be one open file for each\n" " distinct file name (for > and >>) or one subordinate process for each distinct\n" " value of the piped-to command (for |). Output-formatting flags are taken from\n" " the main command line.\n" "\n" " You can use any of the output-format command-line flags, e.g. --ocsv, --ofs,\n" " etc., to control the format of the output. See also %s -h.\n" "\n" " emit with redirect and tee with redirect are identical, except tee can only\n" " output $*.\n" "\n" " Example: mlr --from f.dat put 'tee > \"/tmp/data-\".$a, $*'\n" " Example: mlr --from f.dat put 'tee >> \"/tmp/data-\".$a.$b, $*'\n" " Example: mlr --from f.dat put 'tee > stderr, $*'\n" " Example: mlr --from f.dat put -q 'tee | \"tr \[a-z\\] \[A-Z\\]\", $*'\n" " Example: mlr --from f.dat put -q 'tee | \"tr \[a-z\\] \[A-Z\\] > /tmp/data-\".$a, $*'\n" " Example: mlr --from f.dat put -q 'tee | \"gzip > /tmp/data-\".$a.\".gz\", $*'\n" " Example: mlr --from f.dat put -q --ojson 'tee | \"gzip > /tmp/data-\".$a.\".gz\", $*'\n", MLR_GLOBALS.bargv0); } static void mlr_dsl_true_keyword_usage(FILE* ostream) { fprintf(ostream, "true: the boolean literal value.\n" ); } static void mlr_dsl_unset_keyword_usage(FILE* ostream) { fprintf(ostream, "unset: clears field(s) from the current record, or an out-of-stream or local variable.\n" "\n" " Example: mlr --from f.dat put 'unset $x'\n" " Example: mlr --from f.dat put 'unset $*'\n" " Example: mlr --from f.dat put 'for (k, v in $*) { if (k =~ \"a.*\") { unset $[k] } }'\n" " Example: mlr --from f.dat put '...; unset @sums'\n" " Example: mlr --from f.dat put '...; unset @sums[\"green\"]'\n" " Example: mlr --from f.dat put '...; unset @*'\n"); } static void mlr_dsl_var_keyword_usage(FILE* ostream) { fprintf(ostream, "var: declares an untyped local variable in the current curly-braced scope.\n" "Examples: 'var a=1', 'var xyz=\"\"'\n" ); } static void mlr_dsl_while_keyword_usage(FILE* ostream) { fprintf(ostream, "while: introduces a while loop, or with \"do\", introduces a do-while loop.\n" "The body statements must be wrapped in curly braces.\n" ); } static void mlr_dsl_ENV_keyword_usage(FILE *ostream) { fprintf(ostream, "ENV: access to environment variables by name, e.g. '$home = ENV[\"HOME\"]'\n" ); } static void mlr_dsl_FILENAME_keyword_usage(FILE *ostream) { fprintf(ostream, "FILENAME: evaluates to the name of the current file being processed.\n" ); } static void mlr_dsl_FILENUM_keyword_usage(FILE *ostream) { fprintf(ostream, "FILENUM: evaluates to the number of the current file being processed,\n" "starting with 1.\n" ); } static void mlr_dsl_FNR_keyword_usage(FILE *ostream) { fprintf(ostream, "FNR: evaluates to the number of the current record within the current file\n" "being processed, starting with 1. Resets at the start of each file.\n" ); } static void mlr_dsl_IFS_keyword_usage(FILE *ostream) { fprintf(ostream, "IFS: evaluates to the input field separator from the command line.\n" ); } static void mlr_dsl_IPS_keyword_usage(FILE *ostream) { fprintf(ostream, "IPS: evaluates to the input pair separator from the command line.\n" ); } static void mlr_dsl_IRS_keyword_usage(FILE *ostream) { fprintf(ostream, "IRS: evaluates to the input record separator from the command line,\n" "or to LF or CRLF from the input data if in autodetect mode (which is\n" "the default).\n" ); } static void mlr_dsl_M_E_keyword_usage(FILE *ostream) { fprintf(ostream, "M_E: the mathematical constant e.\n" ); } static void mlr_dsl_M_PI_keyword_usage(FILE *ostream) { fprintf(ostream, "M_PI: the mathematical constant pi.\n" ); } static void mlr_dsl_NF_keyword_usage(FILE *ostream) { fprintf(ostream, "NF: evaluates to the number of fields in the current record.\n" ); } static void mlr_dsl_NR_keyword_usage(FILE *ostream) { fprintf(ostream, "NR: evaluates to the number of the current record over all files\n" "being processed, starting with 1. Does not reset at the start of each file.\n" ); } static void mlr_dsl_OFS_keyword_usage(FILE *ostream) { fprintf(ostream, "OFS: evaluates to the output field separator from the command line.\n" ); } static void mlr_dsl_OPS_keyword_usage(FILE *ostream) { fprintf(ostream, "OPS: evaluates to the output pair separator from the command line.\n" ); } static void mlr_dsl_ORS_keyword_usage(FILE *ostream) { fprintf(ostream, "ORS: evaluates to the output record separator from the command line,\n" "or to LF or CRLF from the input data if in autodetect mode (which is\n" "the default).\n" ); }