2

考虑以下 CSV:

email/1,email/2
abc@xyz.org,bob@pass.com

您可以使用Miller轻松地将其转换为 JSON(考虑到键定义的路径):

mlr --icsv --ojson --jflatsep '/' cat file.csv
[ { "email": ["abc@xyz.org", "bob@pass.com"] } ]

现在,如果路径在 CSV 中索引为 0(这肯定更常见):

email/0,email/1
abc@xyz.org,bob@pass.com

然后,在没有字段名称的先验知识的情况下,您将不得不重写整个转换:

编辑:/FLATSEP内置变量替换硬编码:

mlr --icsv --flatsep '/' put -q '
    begin { @labels = []; print "[" }

    # translate the original CSV header from 0-indexed to 1-indexed
    NR == 1 {
        i = 1;
        for (k in $*) {
            @labels[i] = joinv( apply( splita(k,FLATSEP), func(e) {
                return typeof(e) == "int" ? e+1 : e
            }), FLATSEP );
            i += 1;
        }
    }

    NR > 1 { print @object, "," }

    # create an object from the translated labels and the row values
    o = {};
    i = 1;
    for (k,v in $*) {
        o[@labels[i]] = v;
        i += 1;
    }
    @object = arrayify( unflatten(o,FLATSEP) );

    end { if (NR > 0) { print @object } print "]" }
' file.csv

我想知道我是否遗漏了一些明显的东西,比如命令行选项或用put动词重命名字段的方法,或者其他什么?也欢迎您对前面的代码提供您的见解,因为我对我的 Miller 的编程技能并不十分自信。


更新:

使用 @aborruso预处理 CSV 标头的方法,这可以简化为:注意
我没有保留该regextract部分,因为这意味着提前知道 CSV 标头。

mlr --csv -N --flatsep '/' put '
    NR == 1 {
        for (i,k in $*) {
            $[i] = joinv( apply( splita(k,FLATSEP), func(e) {
                return typeof(e) == "int" ? e+1 : e
            }), FLATSEP );
        }
    }
' file.csv |
mlr --icsv --flatsep '/' --ojson cat

即使有诸如使用rename动词(当您提前知道标头时)或预处理 CSV 标头之类的解决方法,我仍然希望米勒的作者可以添加一个额外的命令行选项来处理这种0-indexed外部数据;在某些情况下,添加(and ) 之DSL类的函数也可能很有用。arrayify0flatten0

4

1 回答 1

2

我想知道我是否遗漏了一些明显的东西,比如命令行选项或用 put 动词重命名字段的方法,或者其他什么?

从此开始

email/0,email/1
abc@xyz.org,bob@pass.com

您可以使用隐式 CSV 标头并运行

mlr --csv -N put 'if (NR == 1) {for (k in $*) {$[k] = "email/".string(int(regextract($[k],"[0-9]+"))+1)}}' input.csv

具有

email/1,email/2
abc@xyz.org,bob@pass.com
于 2022-02-07T08:04:15.450 回答