有没有一种简单的方法可以使用 Miller 将具有 0 索引路径的 CSV 作为键转换为 JSON?
Is there a simple way to convert a CSV with 0-indexed paths as keys to JSON with Miller?
考虑以下 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
然后,在事先不知道字段名称的情况下,你必须重写整个转换:
编辑: 将 hard-coded /
替换为 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 of pre-processing CSV header,这可以减少到:
注意:我没有保留regextract
部分,因为这意味着提前知道CSVheader。
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
动词(当您提前知道 header 时)或 pre-processing CSV header,我仍然希望Miller 的作者可以添加一个额外的 command-line 选项来处理这种 0-indexed 外部数据;添加 DSL
函数,如 arrayify0
(和 flatten0
)在某些情况下也可能有用。
I would like to know if I'm missing something obvious, like a command line option or a way to rename the fields with put verb, or maybe something else?
从此开始
email/0,email/1
abc@xyz.org,bob@pass.com
您可以使用隐式 CSV header 和 运行
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
考虑以下 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
然后,在事先不知道字段名称的情况下,你必须重写整个转换:
编辑: 将 hard-coded /
替换为 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
注意:我没有保留regextract
部分,因为这意味着提前知道CSVheader。
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
动词(当您提前知道 header 时)或 pre-processing CSV header,我仍然希望Miller 的作者可以添加一个额外的 command-line 选项来处理这种 0-indexed 外部数据;添加 DSL
函数,如 arrayify0
(和 flatten0
)在某些情况下也可能有用。
I would like to know if I'm missing something obvious, like a command line option or a way to rename the fields with put verb, or maybe something else?
从此开始
email/0,email/1
abc@xyz.org,bob@pass.com
您可以使用隐式 CSV header 和 运行
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