mirror of
https://github.com/johnkerl/miller.git
synced 2026-08-01 20:12:19 +00:00
Before/after options for reorder verb (#510)
* mlr reorder -b/-a * go test data * c impl
This commit is contained in:
parent
d00e6cf1d2
commit
2e9a695eb0
46 changed files with 411 additions and 86 deletions
|
|
@ -2,21 +2,28 @@
|
|||
#include "containers/lrec.h"
|
||||
#include "containers/sllv.h"
|
||||
#include "containers/hss.h"
|
||||
#include "containers/mixutil.h"
|
||||
#include "mapping/mappers.h"
|
||||
#include "cli/argparse.h"
|
||||
|
||||
typedef struct _mapper_reorder_state_t {
|
||||
ap_state_t* pargp;
|
||||
slls_t* pfield_name_list;
|
||||
int put_at_end;
|
||||
hss_t* pfield_name_set;
|
||||
char* before_field_name;
|
||||
char* after_field_name;
|
||||
} mapper_reorder_state_t;
|
||||
|
||||
static void mapper_reorder_usage(FILE* o, char* argv0, char* verb);
|
||||
static mapper_t* mapper_reorder_parse_cli(int* pargi, int argc, char** argv,
|
||||
cli_reader_opts_t* _, cli_writer_opts_t* __);
|
||||
static mapper_t* mapper_reorder_alloc(ap_state_t* pargp, slls_t* pfield_name_list, int put_at_end);
|
||||
static mapper_t* mapper_reorder_alloc(ap_state_t* pargp, slls_t* pfield_name_list,
|
||||
int put_at_end, char* before_field_name, char* after_field_name);
|
||||
static void mapper_reorder_free(mapper_t* pmapper, context_t* _);
|
||||
static sllv_t* mapper_reorder_process(lrec_t* pinrec, context_t* pctx, void* pvstate);
|
||||
static sllv_t* mapper_reorder_to_start(lrec_t* pinrec, context_t* pctx, void* pvstate);
|
||||
static sllv_t* mapper_reorder_to_end(lrec_t* pinrec, context_t* pctx, void* pvstate);
|
||||
static sllv_t* mapper_reorder_before(lrec_t* pinrec, context_t* pctx, void* pvstate);
|
||||
static sllv_t* mapper_reorder_after(lrec_t* pinrec, context_t* pctx, void* pvstate);
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
mapper_setup_t mapper_reorder_setup = {
|
||||
|
|
@ -29,28 +36,36 @@ mapper_setup_t mapper_reorder_setup = {
|
|||
// ----------------------------------------------------------------
|
||||
static void mapper_reorder_usage(FILE* o, char* argv0, char* verb) {
|
||||
fprintf(o, "Usage: %s %s [options]\n", argv0, verb);
|
||||
fprintf(o, "-f {a,b,c} Field names to reorder.\n");
|
||||
fprintf(o, "-e Put specified field names at record end: default is to put\n");
|
||||
fprintf(o, " them at record start.\n");
|
||||
fprintf(o, "-f {a,b,c} Field names to reorder.\n");
|
||||
fprintf(o, "-e Put specified field names at record end: default is to put\n");
|
||||
fprintf(o, " them at record start.\n");
|
||||
fprintf(o, "-b {x} Put field names specified with -f before field name specified by {x},\n");
|
||||
fprintf(o, " if any. If {x} isn't present in a given record, the specified fields\n");
|
||||
fprintf(o, " will not be moved.\n");
|
||||
fprintf(o, "-a {x} Put field names specified with -f after field name specified by {x},\n");
|
||||
fprintf(o, " if any. If {x} isn't present in a given record, the specified fields\n");
|
||||
fprintf(o, " will not be moved.\n");
|
||||
fprintf(o, "Examples:\n");
|
||||
fprintf(o, "%s %s -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"a=1,b=2,d=4,c=3\".\n",
|
||||
argv0, verb);
|
||||
fprintf(o, "%s %s -e -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"d=4,c=3,a=1,b=2\".\n",
|
||||
argv0, verb);
|
||||
fprintf(o, "%s %s -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"a=1,b=2,d=4,c=3\".\n", argv0, verb);
|
||||
fprintf(o, "%s %s -e -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"d=4,c=3,a=1,b=2\".\n", argv0, verb);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static mapper_t* mapper_reorder_parse_cli(int* pargi, int argc, char** argv,
|
||||
cli_reader_opts_t* _, cli_writer_opts_t* __)
|
||||
{
|
||||
slls_t* pfield_name_list = NULL;
|
||||
int put_at_end = FALSE;
|
||||
slls_t* pfield_name_list = NULL;
|
||||
int put_at_end = FALSE;
|
||||
char* before_field_name = NULL;
|
||||
char* after_field_name = NULL;
|
||||
|
||||
char* verb = argv[(*pargi)++];
|
||||
|
||||
ap_state_t* pstate = ap_alloc();
|
||||
ap_define_string_list_flag(pstate, "-f", &pfield_name_list);
|
||||
ap_define_true_flag(pstate, "-e", &put_at_end);
|
||||
ap_define_string_flag(pstate, "-b", &before_field_name);
|
||||
ap_define_string_flag(pstate, "-a", &after_field_name);
|
||||
|
||||
if (!ap_parse(pstate, verb, pargi, argc, argv)) {
|
||||
mapper_reorder_usage(stderr, argv[0], verb);
|
||||
|
|
@ -62,50 +77,169 @@ static mapper_t* mapper_reorder_parse_cli(int* pargi, int argc, char** argv,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return mapper_reorder_alloc(pstate, pfield_name_list, put_at_end);
|
||||
return mapper_reorder_alloc(pstate, pfield_name_list, put_at_end, before_field_name, after_field_name);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static mapper_t* mapper_reorder_alloc(ap_state_t* pargp, slls_t* pfield_name_list, int put_at_end) {
|
||||
static mapper_t* mapper_reorder_alloc(ap_state_t* pargp, slls_t* pfield_name_list,
|
||||
int put_at_end, char* before_field_name, char* after_field_name)
|
||||
{
|
||||
mapper_t* pmapper = mlr_malloc_or_die(sizeof(mapper_t));
|
||||
|
||||
mapper_reorder_state_t* pstate = mlr_malloc_or_die(sizeof(mapper_reorder_state_t));
|
||||
pstate->pargp = pargp;
|
||||
pstate->pfield_name_list = pfield_name_list;
|
||||
pstate->put_at_end = put_at_end;
|
||||
if (!put_at_end)
|
||||
slls_reverse(pstate->pfield_name_list);
|
||||
pstate->pfield_name_list = pfield_name_list;
|
||||
pstate->pfield_name_set = hss_from_slls(pfield_name_list);
|
||||
pstate->before_field_name = before_field_name;
|
||||
pstate->after_field_name = after_field_name;
|
||||
|
||||
pmapper->pvstate = (void*)pstate;
|
||||
pmapper->pprocess_func = mapper_reorder_process;
|
||||
pmapper->pfree_func = mapper_reorder_free;
|
||||
pmapper->pvstate = (void*)pstate;
|
||||
|
||||
if (put_at_end) {
|
||||
pmapper->pprocess_func = mapper_reorder_to_end;
|
||||
} else if (before_field_name != NULL) {
|
||||
pmapper->pprocess_func = mapper_reorder_before;
|
||||
} else if (after_field_name != NULL) {
|
||||
pmapper->pprocess_func = mapper_reorder_after;
|
||||
} else {
|
||||
pmapper->pprocess_func = mapper_reorder_to_start;
|
||||
slls_reverse(pstate->pfield_name_list);
|
||||
}
|
||||
pmapper->pfree_func = mapper_reorder_free;
|
||||
|
||||
return pmapper;
|
||||
}
|
||||
|
||||
static void mapper_reorder_free(mapper_t* pmapper, context_t* _) {
|
||||
mapper_reorder_state_t* pstate = pmapper->pvstate;
|
||||
if (pstate->pfield_name_list != NULL)
|
||||
slls_free(pstate->pfield_name_list);
|
||||
slls_free(pstate->pfield_name_list);
|
||||
hss_free(pstate->pfield_name_set);
|
||||
ap_free(pstate->pargp);
|
||||
free(pstate);
|
||||
free(pmapper);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static sllv_t* mapper_reorder_process(lrec_t* pinrec, context_t* pctx, void* pvstate) {
|
||||
static sllv_t* mapper_reorder_to_start(lrec_t* pinrec, context_t* pctx, void* pvstate) {
|
||||
mapper_reorder_state_t* pstate = (mapper_reorder_state_t*)pvstate;
|
||||
if (pinrec != NULL) {
|
||||
if (!pstate->put_at_end) {
|
||||
// OK since the field-name list was reversed at construction time.
|
||||
for (sllse_t* pe = pstate->pfield_name_list->phead; pe != NULL; pe = pe->pnext)
|
||||
lrec_move_to_head(pinrec, pe->value);
|
||||
} else {
|
||||
for (sllse_t* pe = pstate->pfield_name_list->phead; pe != NULL; pe = pe->pnext)
|
||||
lrec_move_to_tail(pinrec, pe->value);
|
||||
// OK since the field-name list was reversed at construction time.
|
||||
for (sllse_t* pe = pstate->pfield_name_list->phead; pe != NULL; pe = pe->pnext) {
|
||||
lrec_move_to_head(pinrec, pe->value);
|
||||
}
|
||||
return sllv_single(pinrec);
|
||||
} else {
|
||||
return sllv_single(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static sllv_t* mapper_reorder_to_end(lrec_t* pinrec, context_t* pctx, void* pvstate) {
|
||||
mapper_reorder_state_t* pstate = (mapper_reorder_state_t*)pvstate;
|
||||
if (pinrec != NULL) {
|
||||
for (sllse_t* pe = pstate->pfield_name_list->phead; pe != NULL; pe = pe->pnext) {
|
||||
lrec_move_to_tail(pinrec, pe->value);
|
||||
}
|
||||
return sllv_single(pinrec);
|
||||
} else {
|
||||
return sllv_single(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static sllv_t* mapper_reorder_before(lrec_t* pinrec, context_t* pctx, void* pvstate) {
|
||||
mapper_reorder_state_t* pstate = (mapper_reorder_state_t*)pvstate;
|
||||
if (pinrec != NULL) {
|
||||
char* bvalue = lrec_get(pinrec, pstate->before_field_name);
|
||||
if (bvalue == NULL) {
|
||||
return sllv_single(pinrec);
|
||||
}
|
||||
|
||||
lrec_t* poutrec = lrec_unbacked_alloc();
|
||||
lrece_t* pe = pinrec->phead;
|
||||
|
||||
for (; pe != NULL; pe = pe->pnext) {
|
||||
if (streq(pe->key, pstate->before_field_name)) {
|
||||
break;
|
||||
}
|
||||
if (!hss_has(pstate->pfield_name_set, pe->key)) {
|
||||
lrec_put(poutrec, mlr_strdup_or_die(pe->key), mlr_strdup_or_die(pe->value),
|
||||
FREE_ENTRY_KEY|FREE_ENTRY_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
for (sllse_t* pf = pstate->pfield_name_list->phead; pf != NULL; pf = pf->pnext) {
|
||||
char* field_name = pf->value;
|
||||
char* value = lrec_get(pinrec, field_name);
|
||||
if (value != NULL) {
|
||||
lrec_put(poutrec, field_name, mlr_strdup_or_die(value), FREE_ENTRY_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
lrec_put(poutrec, pstate->before_field_name, mlr_strdup_or_die(bvalue), FREE_ENTRY_VALUE);
|
||||
|
||||
for (; pe != NULL; pe = pe->pnext) {
|
||||
if (streq(pe->key, pstate->before_field_name)) {
|
||||
continue;
|
||||
}
|
||||
if (!hss_has(pstate->pfield_name_set, pe->key)) {
|
||||
lrec_put(poutrec, mlr_strdup_or_die(pe->key), mlr_strdup_or_die(pe->value),
|
||||
FREE_ENTRY_KEY|FREE_ENTRY_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
lrec_free(pinrec);
|
||||
return sllv_single(poutrec);
|
||||
} else {
|
||||
return sllv_single(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static sllv_t* mapper_reorder_after(lrec_t* pinrec, context_t* pctx, void* pvstate) {
|
||||
mapper_reorder_state_t* pstate = (mapper_reorder_state_t*)pvstate;
|
||||
if (pinrec != NULL) {
|
||||
char* avalue = lrec_get(pinrec, pstate->after_field_name);
|
||||
if (avalue == NULL) {
|
||||
return sllv_single(pinrec);
|
||||
}
|
||||
|
||||
lrec_t* poutrec = lrec_unbacked_alloc();
|
||||
lrece_t* pe = pinrec->phead;
|
||||
|
||||
for (; pe != NULL; pe = pe->pnext) {
|
||||
if (streq(pe->key, pstate->after_field_name)) {
|
||||
break;
|
||||
}
|
||||
if (!hss_has(pstate->pfield_name_set, pe->key)) {
|
||||
lrec_put(poutrec, mlr_strdup_or_die(pe->key), mlr_strdup_or_die(pe->value),
|
||||
FREE_ENTRY_KEY|FREE_ENTRY_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
lrec_put(poutrec, pstate->after_field_name, mlr_strdup_or_die(avalue), FREE_ENTRY_VALUE);
|
||||
|
||||
for (sllse_t* pf = pstate->pfield_name_list->phead; pf != NULL; pf = pf->pnext) {
|
||||
char* field_name = pf->value;
|
||||
char* value = lrec_get(pinrec, field_name);
|
||||
if (value != NULL) {
|
||||
lrec_put(poutrec, field_name, mlr_strdup_or_die(value), FREE_ENTRY_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
for (; pe != NULL; pe = pe->pnext) {
|
||||
if (streq(pe->key, pstate->after_field_name)) {
|
||||
continue;
|
||||
}
|
||||
if (!hss_has(pstate->pfield_name_set, pe->key)) {
|
||||
lrec_put(poutrec, mlr_strdup_or_die(pe->key), mlr_strdup_or_die(pe->value),
|
||||
FREE_ENTRY_KEY|FREE_ENTRY_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
lrec_free(pinrec);
|
||||
return sllv_single(poutrec);
|
||||
} else {
|
||||
return sllv_single(NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52706,6 +52706,36 @@ y/,x/,i/,b/,a/
|
|||
0.803142013402256216,0.000047786161325772/,3/,pan/,zee/
|
||||
0.573903236805416328,0.676537984365847889/,4/,hat/,zee/
|
||||
|
||||
mlr --from ./reg_test/input/reorder.dkvp reorder -f x,y -b u
|
||||
s=1,t=2,x=6,y=7,u=3,v=4,w=5,z=8
|
||||
|
||||
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,v -b x
|
||||
s=1,t=2,w=5,u=3,v=4,x=6,y=7,z=8
|
||||
|
||||
mlr --from ./reg_test/input/reorder.dkvp reorder -f z,w,s -b v
|
||||
t=2,u=3,z=8,w=5,s=1,v=4,x=6,y=7
|
||||
|
||||
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,v -b nonesuch
|
||||
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8
|
||||
|
||||
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,nonesuch -b x
|
||||
s=1,t=2,v=4,w=5,u=3,x=6,y=7,z=8
|
||||
|
||||
mlr --from ./reg_test/input/reorder.dkvp reorder -f x,y -a u
|
||||
s=1,t=2,u=3,x=6,y=7,v=4,w=5,z=8
|
||||
|
||||
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,v -a x
|
||||
s=1,t=2,w=5,x=6,u=3,v=4,y=7,z=8
|
||||
|
||||
mlr --from ./reg_test/input/reorder.dkvp reorder -f z,w,s -a v
|
||||
t=2,u=3,v=4,z=8,w=5,s=1,x=6,y=7
|
||||
|
||||
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,v -a nonesuch
|
||||
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8
|
||||
|
||||
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,nonesuch -a x
|
||||
s=1,t=2,v=4,w=5,x=6,u=3,y=7,z=8
|
||||
|
||||
mlr --icsv --otsv -N cat
|
||||
a b c
|
||||
1 2 3
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ EXTRA_DIST= \
|
|||
regex.dkvp \
|
||||
regularize.dkvp \
|
||||
remove-empty-columns.csv \
|
||||
reorder.dkvp \
|
||||
repeat-input.dat \
|
||||
repeats.dkvp \
|
||||
reshape-long-ragged.dkvp \
|
||||
|
|
|
|||
1
c/reg_test/input/reorder.dkvp
Normal file
1
c/reg_test/input/reorder.dkvp
Normal file
|
|
@ -0,0 +1 @@
|
|||
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8
|
||||
|
|
@ -6469,6 +6469,18 @@ run_mlr --implicit-csv-header --icsv --ifs /, --opprint cut -x -f 2 $indir/mult
|
|||
run_mlr --csv -N reorder -f 1,3,2,5,4 $indir/multi-sep.csv-crlf
|
||||
run_mlr --csv -N reorder -f 5,4,3,2,1 $indir/multi-sep.csv-crlf
|
||||
|
||||
run_mlr --from $indir/reorder.dkvp reorder -f x,y -b u
|
||||
run_mlr --from $indir/reorder.dkvp reorder -f u,v -b x
|
||||
run_mlr --from $indir/reorder.dkvp reorder -f z,w,s -b v
|
||||
run_mlr --from $indir/reorder.dkvp reorder -f u,v -b nonesuch
|
||||
run_mlr --from $indir/reorder.dkvp reorder -f u,nonesuch -b x
|
||||
|
||||
run_mlr --from $indir/reorder.dkvp reorder -f x,y -a u
|
||||
run_mlr --from $indir/reorder.dkvp reorder -f u,v -a x
|
||||
run_mlr --from $indir/reorder.dkvp reorder -f z,w,s -a v
|
||||
run_mlr --from $indir/reorder.dkvp reorder -f u,v -a nonesuch
|
||||
run_mlr --from $indir/reorder.dkvp reorder -f u,nonesuch -a x
|
||||
|
||||
run_mlr --icsv --otsv -N cat <<EOF
|
||||
a,b,c
|
||||
1,2,3
|
||||
|
|
|
|||
|
|
@ -2042,9 +2042,15 @@ reorder
|
|||
|
||||
$ mlr reorder --help
|
||||
Usage: mlr reorder [options]
|
||||
-f {a,b,c} Field names to reorder.
|
||||
-e Put specified field names at record end: default is to put
|
||||
them at record start.
|
||||
-f {a,b,c} Field names to reorder.
|
||||
-e Put specified field names at record end: default is to put
|
||||
them at record start.
|
||||
-b {x} Put field names specified with -f before field name specified by {x},
|
||||
if any. If {x} isn't present in a given record, the specified fields
|
||||
will not be moved.
|
||||
-a {x} Put field names specified with -f after field name specified by {x},
|
||||
if any. If {x} isn't present in a given record, the specified fields
|
||||
will not be moved.
|
||||
Examples:
|
||||
mlr reorder -f a,b sends input record "d=4,b=2,a=1,c=3" to "a=1,b=2,d=4,c=3".
|
||||
mlr reorder -e -f a,b sends input record "d=4,b=2,a=1,c=3" to "d=4,c=3,a=1,b=2".
|
||||
|
|
|
|||
|
|
@ -514,6 +514,12 @@ Moves specified names to start of record, or end of record.
|
|||
Options:
|
||||
-e Put specified field names at record end: default is to put them at record start.
|
||||
-f {a,b,c} Field names to reorder.
|
||||
-b {x} Put field names specified with -f before field name specified by {x},
|
||||
if any. If {x} isn't present in a given record, the specified fields
|
||||
will not be moved.
|
||||
-a {x} Put field names specified with -f after field name specified by {x},
|
||||
if any. If {x} isn't present in a given record, the specified fields
|
||||
will not be moved.
|
||||
-h|--help Show this message.
|
||||
|
||||
Examples:
|
||||
|
|
|
|||
1
go/regtest/cases/verb-reorder/after-0001/cmd
Normal file
1
go/regtest/cases/verb-reorder/after-0001/cmd
Normal file
|
|
@ -0,0 +1 @@
|
|||
mlr --from regtest/input/reorder.dkvp reorder -f x,y -a u
|
||||
1
go/regtest/cases/verb-reorder/after-0001/expout
Normal file
1
go/regtest/cases/verb-reorder/after-0001/expout
Normal file
|
|
@ -0,0 +1 @@
|
|||
s=1,t=2,u=3,x=6,y=7,v=4,w=5,z=8
|
||||
1
go/regtest/cases/verb-reorder/after-0002/cmd
Normal file
1
go/regtest/cases/verb-reorder/after-0002/cmd
Normal file
|
|
@ -0,0 +1 @@
|
|||
mlr --from regtest/input/reorder.dkvp reorder -f u,v -a x
|
||||
1
go/regtest/cases/verb-reorder/after-0002/expout
Normal file
1
go/regtest/cases/verb-reorder/after-0002/expout
Normal file
|
|
@ -0,0 +1 @@
|
|||
s=1,t=2,w=5,x=6,u=3,v=4,y=7,z=8
|
||||
1
go/regtest/cases/verb-reorder/after-0003/cmd
Normal file
1
go/regtest/cases/verb-reorder/after-0003/cmd
Normal file
|
|
@ -0,0 +1 @@
|
|||
mlr --from regtest/input/reorder.dkvp reorder -f z,w,s -a v
|
||||
0
go/regtest/cases/verb-reorder/after-0003/experr
Normal file
0
go/regtest/cases/verb-reorder/after-0003/experr
Normal file
1
go/regtest/cases/verb-reorder/after-0003/expout
Normal file
1
go/regtest/cases/verb-reorder/after-0003/expout
Normal file
|
|
@ -0,0 +1 @@
|
|||
t=2,u=3,v=4,z=8,w=5,s=1,x=6,y=7
|
||||
1
go/regtest/cases/verb-reorder/after-0004/cmd
Normal file
1
go/regtest/cases/verb-reorder/after-0004/cmd
Normal file
|
|
@ -0,0 +1 @@
|
|||
mlr --from regtest/input/reorder.dkvp reorder -f u,v -a nonesuch
|
||||
0
go/regtest/cases/verb-reorder/after-0004/experr
Normal file
0
go/regtest/cases/verb-reorder/after-0004/experr
Normal file
1
go/regtest/cases/verb-reorder/after-0004/expout
Normal file
1
go/regtest/cases/verb-reorder/after-0004/expout
Normal file
|
|
@ -0,0 +1 @@
|
|||
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8
|
||||
1
go/regtest/cases/verb-reorder/after-0005/cmd
Normal file
1
go/regtest/cases/verb-reorder/after-0005/cmd
Normal file
|
|
@ -0,0 +1 @@
|
|||
mlr --from regtest/input/reorder.dkvp reorder -f u,nonesuch -a x
|
||||
0
go/regtest/cases/verb-reorder/after-0005/experr
Normal file
0
go/regtest/cases/verb-reorder/after-0005/experr
Normal file
1
go/regtest/cases/verb-reorder/after-0005/expout
Normal file
1
go/regtest/cases/verb-reorder/after-0005/expout
Normal file
|
|
@ -0,0 +1 @@
|
|||
s=1,t=2,v=4,w=5,x=6,u=3,y=7,z=8
|
||||
0
go/regtest/cases/verb-reorder/at-end-0001/experr
Normal file
0
go/regtest/cases/verb-reorder/at-end-0001/experr
Normal file
0
go/regtest/cases/verb-reorder/at-start-0001/experr
Normal file
0
go/regtest/cases/verb-reorder/at-start-0001/experr
Normal file
1
go/regtest/cases/verb-reorder/before-0001/cmd
Normal file
1
go/regtest/cases/verb-reorder/before-0001/cmd
Normal file
|
|
@ -0,0 +1 @@
|
|||
mlr --from regtest/input/reorder.dkvp reorder -f x,y -b u
|
||||
0
go/regtest/cases/verb-reorder/before-0001/experr
Normal file
0
go/regtest/cases/verb-reorder/before-0001/experr
Normal file
1
go/regtest/cases/verb-reorder/before-0001/expout
Normal file
1
go/regtest/cases/verb-reorder/before-0001/expout
Normal file
|
|
@ -0,0 +1 @@
|
|||
s=1,t=2,x=6,y=7,u=3,v=4,w=5,z=8
|
||||
1
go/regtest/cases/verb-reorder/before-0002/cmd
Normal file
1
go/regtest/cases/verb-reorder/before-0002/cmd
Normal file
|
|
@ -0,0 +1 @@
|
|||
mlr --from regtest/input/reorder.dkvp reorder -f u,v -b x
|
||||
0
go/regtest/cases/verb-reorder/before-0002/experr
Normal file
0
go/regtest/cases/verb-reorder/before-0002/experr
Normal file
1
go/regtest/cases/verb-reorder/before-0002/expout
Normal file
1
go/regtest/cases/verb-reorder/before-0002/expout
Normal file
|
|
@ -0,0 +1 @@
|
|||
s=1,t=2,w=5,u=3,v=4,x=6,y=7,z=8
|
||||
1
go/regtest/cases/verb-reorder/before-0003/cmd
Normal file
1
go/regtest/cases/verb-reorder/before-0003/cmd
Normal file
|
|
@ -0,0 +1 @@
|
|||
mlr --from regtest/input/reorder.dkvp reorder -f z,w,s -b v
|
||||
0
go/regtest/cases/verb-reorder/before-0003/experr
Normal file
0
go/regtest/cases/verb-reorder/before-0003/experr
Normal file
1
go/regtest/cases/verb-reorder/before-0003/expout
Normal file
1
go/regtest/cases/verb-reorder/before-0003/expout
Normal file
|
|
@ -0,0 +1 @@
|
|||
t=2,u=3,z=8,w=5,s=1,v=4,x=6,y=7
|
||||
1
go/regtest/cases/verb-reorder/before-0004/cmd
Normal file
1
go/regtest/cases/verb-reorder/before-0004/cmd
Normal file
|
|
@ -0,0 +1 @@
|
|||
mlr --from regtest/input/reorder.dkvp reorder -f u,v -b nonesuch
|
||||
0
go/regtest/cases/verb-reorder/before-0004/experr
Normal file
0
go/regtest/cases/verb-reorder/before-0004/experr
Normal file
1
go/regtest/cases/verb-reorder/before-0004/expout
Normal file
1
go/regtest/cases/verb-reorder/before-0004/expout
Normal file
|
|
@ -0,0 +1 @@
|
|||
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8
|
||||
1
go/regtest/cases/verb-reorder/before-0005/cmd
Normal file
1
go/regtest/cases/verb-reorder/before-0005/cmd
Normal file
|
|
@ -0,0 +1 @@
|
|||
mlr --from regtest/input/reorder.dkvp reorder -f u,nonesuch -b x
|
||||
0
go/regtest/cases/verb-reorder/before-0005/experr
Normal file
0
go/regtest/cases/verb-reorder/before-0005/experr
Normal file
1
go/regtest/cases/verb-reorder/before-0005/expout
Normal file
1
go/regtest/cases/verb-reorder/before-0005/expout
Normal file
|
|
@ -0,0 +1 @@
|
|||
s=1,t=2,v=4,w=5,u=3,x=6,y=7,z=8
|
||||
1
go/regtest/input/reorder.dkvp
Normal file
1
go/regtest/input/reorder.dkvp
Normal file
|
|
@ -0,0 +1 @@
|
|||
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8
|
||||
|
|
@ -26,26 +26,26 @@ func transformerReorderUsage(
|
|||
doExit bool,
|
||||
exitCode int,
|
||||
) {
|
||||
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameReorder)
|
||||
argv0 := lib.MlrExeName()
|
||||
verb := verbNameReorder
|
||||
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
|
||||
fmt.Fprint(o,
|
||||
`Moves specified names to start of record, or end of record.
|
||||
`)
|
||||
fmt.Fprintf(o, "Options:\n")
|
||||
fmt.Fprintf(o, "-e Put specified field names at record end: default is to put them at record start.\n")
|
||||
fmt.Fprintf(o, "-f {a,b,c} Field names to reorder.\n")
|
||||
fmt.Fprintf(o, "-b {x} Put field names specified with -f before field name specified by {x},\n")
|
||||
fmt.Fprintf(o, " if any. If {x} isn't present in a given record, the specified fields\n")
|
||||
fmt.Fprintf(o, " will not be moved.\n")
|
||||
fmt.Fprintf(o, "-a {x} Put field names specified with -f after field name specified by {x},\n")
|
||||
fmt.Fprintf(o, " if any. If {x} isn't present in a given record, the specified fields\n")
|
||||
fmt.Fprintf(o, " will not be moved.\n")
|
||||
fmt.Fprintf(o, "-h|--help Show this message.\n")
|
||||
fmt.Fprintf(o, "\n")
|
||||
fmt.Fprintf(o, "Examples:\n")
|
||||
fmt.Fprintf(
|
||||
o,
|
||||
"%s %s -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"a=1,b=2,d=4,c=3\".\n",
|
||||
lib.MlrExeName(), verbNameReorder,
|
||||
)
|
||||
fmt.Fprintf(
|
||||
o,
|
||||
"%s %s -e -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"d=4,c=3,a=1,b=2\".\n",
|
||||
lib.MlrExeName(), verbNameReorder,
|
||||
)
|
||||
fmt.Fprintf(o, "%s %s -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"a=1,b=2,d=4,c=3\".\n", argv0, verb)
|
||||
fmt.Fprintf(o, "%s %s -e -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"d=4,c=3,a=1,b=2\".\n", argv0, verb)
|
||||
|
||||
if doExit {
|
||||
os.Exit(exitCode)
|
||||
|
|
@ -67,6 +67,8 @@ func transformerReorderParseCLI(
|
|||
|
||||
var fieldNames []string = nil
|
||||
putAtEnd := false
|
||||
beforeFieldName := ""
|
||||
afterFieldName := ""
|
||||
|
||||
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
|
||||
opt := args[argi]
|
||||
|
|
@ -81,8 +83,20 @@ func transformerReorderParseCLI(
|
|||
} else if opt == "-f" {
|
||||
fieldNames = cliutil.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
|
||||
|
||||
} else if opt == "-b" {
|
||||
beforeFieldName = cliutil.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
|
||||
afterFieldName = ""
|
||||
putAtEnd = false
|
||||
|
||||
} else if opt == "-a" {
|
||||
afterFieldName = cliutil.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
|
||||
beforeFieldName = ""
|
||||
putAtEnd = false
|
||||
|
||||
} else if opt == "-e" {
|
||||
putAtEnd = true
|
||||
beforeFieldName = ""
|
||||
afterFieldName = ""
|
||||
|
||||
} else {
|
||||
transformerReorderUsage(os.Stderr, true, 1)
|
||||
|
|
@ -96,6 +110,8 @@ func transformerReorderParseCLI(
|
|||
transformer, _ := NewTransformerReorder(
|
||||
fieldNames,
|
||||
putAtEnd,
|
||||
beforeFieldName,
|
||||
afterFieldName,
|
||||
)
|
||||
|
||||
*pargi = argi
|
||||
|
|
@ -105,7 +121,10 @@ func transformerReorderParseCLI(
|
|||
// ----------------------------------------------------------------
|
||||
type TransformerReorder struct {
|
||||
// input
|
||||
fieldNames []string
|
||||
fieldNames []string
|
||||
fieldNamesSet map[string]bool
|
||||
beforeFieldName string
|
||||
afterFieldName string
|
||||
|
||||
// state
|
||||
recordTransformerFunc transforming.RecordTransformerFunc
|
||||
|
|
@ -114,20 +133,26 @@ type TransformerReorder struct {
|
|||
func NewTransformerReorder(
|
||||
fieldNames []string,
|
||||
putAtEnd bool,
|
||||
beforeFieldName string,
|
||||
afterFieldName string,
|
||||
) (*TransformerReorder, error) {
|
||||
|
||||
if !putAtEnd {
|
||||
lib.ReverseStringList(fieldNames)
|
||||
}
|
||||
|
||||
this := &TransformerReorder{
|
||||
fieldNames: fieldNames,
|
||||
fieldNames: fieldNames,
|
||||
fieldNamesSet: lib.StringListToSet(fieldNames),
|
||||
beforeFieldName: beforeFieldName,
|
||||
afterFieldName: afterFieldName,
|
||||
}
|
||||
|
||||
if !putAtEnd {
|
||||
this.recordTransformerFunc = this.reorderToStart
|
||||
} else {
|
||||
if putAtEnd {
|
||||
this.recordTransformerFunc = this.reorderToEnd
|
||||
} else if beforeFieldName != "" {
|
||||
this.recordTransformerFunc = this.reorderBefore
|
||||
} else if afterFieldName != "" {
|
||||
this.recordTransformerFunc = this.reorderAfter
|
||||
} else {
|
||||
this.recordTransformerFunc = this.reorderToStart
|
||||
lib.ReverseStringList(this.fieldNames)
|
||||
}
|
||||
|
||||
return this, nil
|
||||
|
|
@ -173,3 +198,113 @@ func (this *TransformerReorder) reorderToEnd(
|
|||
outputChannel <- inrecAndContext // end-of-stream marker
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
func (this *TransformerReorder) reorderBefore(
|
||||
inrecAndContext *types.RecordAndContext,
|
||||
outputChannel chan<- *types.RecordAndContext,
|
||||
) {
|
||||
if !inrecAndContext.EndOfStream {
|
||||
inrec := inrecAndContext.Record
|
||||
if inrec.Get(this.beforeFieldName) == nil {
|
||||
outputChannel <- inrecAndContext
|
||||
return
|
||||
}
|
||||
|
||||
outrec := types.NewMlrmapAsRecord()
|
||||
pe := inrec.Head
|
||||
|
||||
// * inrec will be GC'ed
|
||||
// * We will use outrec.PutReference not output.PutCopy since inrec will be GC'ed
|
||||
|
||||
for ; pe != nil; pe = pe.Next {
|
||||
if pe.Key == this.beforeFieldName {
|
||||
break
|
||||
}
|
||||
if !this.fieldNamesSet[pe.Key] {
|
||||
outrec.PutReference(pe.Key, pe.Value)
|
||||
}
|
||||
}
|
||||
|
||||
for _, fieldName := range this.fieldNames {
|
||||
value := inrec.Get(fieldName)
|
||||
if value != nil {
|
||||
outrec.PutReference(fieldName, value)
|
||||
}
|
||||
}
|
||||
|
||||
value := inrec.Get(this.beforeFieldName)
|
||||
if value != nil {
|
||||
outrec.PutReference(this.beforeFieldName, value)
|
||||
}
|
||||
|
||||
for ; pe != nil; pe = pe.Next {
|
||||
if pe.Key != this.beforeFieldName && !this.fieldNamesSet[pe.Key] {
|
||||
outrec.PutReference(pe.Key, pe.Value)
|
||||
}
|
||||
}
|
||||
|
||||
for _, fieldName := range this.fieldNames {
|
||||
inrec.MoveToHead(fieldName)
|
||||
}
|
||||
outputChannel <- types.NewRecordAndContext(outrec, &inrecAndContext.Context)
|
||||
|
||||
} else {
|
||||
outputChannel <- inrecAndContext // end-of-stream marker
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
func (this *TransformerReorder) reorderAfter(
|
||||
inrecAndContext *types.RecordAndContext,
|
||||
outputChannel chan<- *types.RecordAndContext,
|
||||
) {
|
||||
if !inrecAndContext.EndOfStream {
|
||||
inrec := inrecAndContext.Record
|
||||
if inrec.Get(this.afterFieldName) == nil {
|
||||
outputChannel <- inrecAndContext
|
||||
return
|
||||
}
|
||||
|
||||
outrec := types.NewMlrmapAsRecord()
|
||||
pe := inrec.Head
|
||||
|
||||
// * inrec will be GC'ed
|
||||
// * We will use outrec.PutReference not output.PutCopy since inrec will be GC'ed
|
||||
|
||||
for ; pe != nil; pe = pe.Next {
|
||||
if pe.Key == this.afterFieldName {
|
||||
break
|
||||
}
|
||||
if !this.fieldNamesSet[pe.Key] {
|
||||
outrec.PutReference(pe.Key, pe.Value)
|
||||
}
|
||||
}
|
||||
|
||||
value := inrec.Get(this.afterFieldName)
|
||||
if value != nil {
|
||||
outrec.PutReference(this.afterFieldName, value)
|
||||
}
|
||||
|
||||
for _, fieldName := range this.fieldNames {
|
||||
value := inrec.Get(fieldName)
|
||||
if value != nil {
|
||||
outrec.PutReference(fieldName, value)
|
||||
}
|
||||
}
|
||||
|
||||
for ; pe != nil; pe = pe.Next {
|
||||
if pe.Key != this.afterFieldName && !this.fieldNamesSet[pe.Key] {
|
||||
outrec.PutReference(pe.Key, pe.Value)
|
||||
}
|
||||
}
|
||||
|
||||
for _, fieldName := range this.fieldNames {
|
||||
inrec.MoveToHead(fieldName)
|
||||
}
|
||||
outputChannel <- types.NewRecordAndContext(outrec, &inrecAndContext.Context)
|
||||
|
||||
} else {
|
||||
outputChannel <- inrecAndContext // end-of-stream marker
|
||||
}
|
||||
}
|
||||
|
|
|
|||
43
go/u/gg
43
go/u/gg
|
|
@ -3,7 +3,7 @@
|
|||
path_to_mlr="./mlr"
|
||||
indir="./regtest/input"
|
||||
|
||||
go build mlr.go
|
||||
#go build mlr.go
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -53,37 +53,16 @@ mention() {
|
|||
|
||||
# ================================================================
|
||||
|
||||
echo 'x=a;b;c' | run_mlr nest -evF -f x
|
||||
echo 'foo=bar,x=a;b;c' | run_mlr nest -evF -f x
|
||||
echo 'x=a;b;c,foo=bar' | run_mlr nest -evF -f x
|
||||
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f x,y -b u
|
||||
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,v -b x
|
||||
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f z,w,s -b v
|
||||
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,v -b nonesuch
|
||||
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,nonesuch -b x
|
||||
|
||||
echo 'x=a;b;c' | run_mlr nest -evR -f x
|
||||
echo 'foo=bar,x=a;b;c' | run_mlr nest -evR -f x
|
||||
echo 'x=a;b;c,foo=bar' | run_mlr nest -evR -f x
|
||||
|
||||
echo 'x=a|b|c' | run_mlr nest -evF -S pipe -f x
|
||||
echo 'foo=bar,x=a|b|c' | run_mlr nest -evF -S pipe -f x
|
||||
echo 'x=a|b|c,foo=bar' | run_mlr nest -evF -S pipe -f x
|
||||
|
||||
echo 'x=a|b|c' | run_mlr nest -evF -S '|' -f x
|
||||
echo 'foo=bar,x=a|b|c' | run_mlr nest -evF -S '|' -f x
|
||||
echo 'x=a|b|c,foo=bar' | run_mlr nest -evF -S '|' -f x
|
||||
|
||||
echo 'x=a;b;c' | run_mlr nest -evR -f x
|
||||
echo 'foo=bar,x=a;b;c' | run_mlr nest -evR -f x
|
||||
echo 'x=a;b;c,foo=bar' | run_mlr nest -evR -f x
|
||||
|
||||
|
||||
echo 'x=a:1;b:2;c:3' | run_mlr nest -epF -f x
|
||||
echo 'foo=bar,x=a:1;b:2;c:3' | run_mlr nest -epF -f x
|
||||
echo 'x=a:1;b:2;c:3,foo=bar' | run_mlr nest -epF -f x
|
||||
|
||||
echo 'x=a:1;b:2;c:3' | run_mlr nest -epR -f x
|
||||
echo 'foo=bar,x=a:1;b:2;c:3' | run_mlr nest -epR -f x
|
||||
echo 'x=a:1;b:2;c:3,foo=bar' | run_mlr nest -epR -f x
|
||||
|
||||
echo 'x_1=a:1,x_2=b:2,x_3=c:3' | run_mlr nest -ivF -f x
|
||||
echo 'foo=bar,x_1=a:1,x_2=b:2,x_3=c:3' | run_mlr nest -ivF -f x
|
||||
echo 'x_1=a:1,x_2=b:2,x_3=c:3,foo=bar' | run_mlr nest -ivF -f x
|
||||
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f x,y -a u
|
||||
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,v -a x
|
||||
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f z,w,s -a v
|
||||
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,v -a nonesuch
|
||||
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,nonesuch -a x
|
||||
|
||||
# ================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue