在 jq 中将逗号分隔文件转换为嵌套 objects json
Converting comma separated file to nested objects json in jq
我有一个 CSV 文件,我想使用 jq 解析并获得嵌套 JSON。我最近开始使用 JQ,我非常喜欢这个工具。我了解基本功能,但解析 csv 文件似乎有点困难,尤其是打印嵌套 objects.
示例输入
基因、外显子、总计、外显子碱基数、总碱基数、外显子碱基分数
PIK3CA,PIK3CA_Exon10;chr1;1000;1500,PIK3CA_Exon13;chr1;1000;1500,PIK3CA_Exon14;chr1;1000;1500,1927879,12993042,0.15
NRAS,NRAS_Exon4;chr1;1000;1500,NRAS_Amp_369;chr1;1000;1500,NRAS_Amp_371;chr1;1000;1500,NRAS_Amp_374;chr1;1000;1500, NRAS_Amp_379;chr1;1000;1500,884111,8062107,0.11
Header 和输入数据解释
第一列始终有一个值。第二列可以有多个外显子(1 个或多个)。您可以看到它在第 2 行有 3 个值,在第 3 行有 5 个值。外显子碱基将始终是倒数第二列,总碱基将是最后一列,外显子碱基分数将是最后一列。
备注
我添加的header是为了解释,可以删除或修改以进行处理
预期输出
{
"Exome regions":[
{
"metric":"PIK3CA",
"value":[
{
"metric":"Exons",
"value":[
"PIK3CA_Exon10",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"PIK3CA_Exon13",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"PIK3CA_Exon14",
{
"chromosome":"chr1",
"start":1000,
"end":1500
}
],
"type":"set"
},
{
"metric":"Fraction of bases",
"value":0.15,
"type":"simple"
},
{
"metric":"Total_bases",
"value":1927879,
"type":"simple"
}
],
"type":"set"
},
{
"metric":"NRAS",
"value":[
{
"metric":"Exons",
"value":[
"NRAS_Exon4",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"NRAS_Amp_369",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"NRAS_Amp_371",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"NRAS_Amp_374",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"NRAS_Amp_379",
{
"chromosome":"chr1",
"start":1000,
"end":1500
}
],
"type":"set"
},
{
"metric":"Fraction of bases",
"value":0.11,
"type":"simple"
},
{
"metric":"Total_bases",
"value":884111,
"type":"simple"
}
],
"type":"set"
}
]
}
提前感谢您的帮助!!
PS:- 我需要添加更多信息,我必须编辑外显子字段并向每个外显子添加 "Chromosomes"、"Start" 和 "End"。在这里我给出了相同的开始和结束,但在实际情况下它因每个外显子而异。你能帮我解决这个问题吗?
此外,这些外显子的输入可以用任何其他字符分隔 too.Right 现在我用“;”分隔它
这是一个解决方案,(a) 根据关于 header 的评论(但见下文)假设没有 header 行; (b) 不 "slurp" 文件(即
不会将整个文件读入内存); (c) 假定 jq 的版本为 inputs
。 (如果你的jq没有inputs
,下面相应修改就很容易了。)
def parse_row:
split(",")
| length as $length
| .[1: $length - 3] as $exons
| { metric : .[0],
value: [ { metric: "Exons",
value: $exons,
type: "set" },
{ metric: "Fraction of bases",
value: (.[$length - 1] | tonumber),
type: "simple"
},
{ metric: "Total_bases",
value: (.[$length - 3] | tonumber),
type: "simple"
}
],
type: "set"
} ;
[inputs | parse_row]
| { "Exome regions": .}
jq 的适当调用应遵循以下几行:
jq -n -R -f program.jq input.txt
这将生成所需的 JSON。
(-R 代表 "raw input"。)
如果输入文件确实有 header 行,只要您删除“-n”command-line 选项,上述解决方案仍然有效。
请注意,虽然输入文件有 comma-separated 个值,但它并不是真正的 CSV 文件。
这是一个使用函数来解析和组装输出的解决方案:
def parse:
[
inputs # read lines
| split(",") # split into columns
| select(length>0) # eliminate blanks
| .[:1] + [.[1:-3]] + .[-3:] # normalize columns
]
;
def simple(n;v): {metric:n, value:v|tonumber, type:"simple"};
def set(n;v): {metric:n, value:v, type:"set"};
def region:
set(.[0]; [
set("Exons"; .[1]),
simple("Fraction of bases"; .[2]),
simple("Total_bases"; .[3])
]
)
;
{
"Exome regions": parse | map(region)
}
示例 运行(假设过滤器在 filter.jq
中,数据在 data.json
中)
$ jq -M -Rnr -f filter.jq data.json
{
"Exome regions": [
{
"metric": "PIK3CA",
"value": [
{
"metric": "Exons",
"value": [
"PIK3CA_Exon10",
"PIK3CA_Exon13",
"PIK3CA_Exon14"
],
"type": "set"
},
{
"metric": "Fraction of bases",
"value": 1927879,
"type": "simple"
},
{
"metric": "Total_bases",
"value": 12993042,
"type": "simple"
}
],
"type": "set"
},
{
"metric": "NRAS",
"value": [
{
"metric": "Exons",
"value": [
"NRAS_Exon4",
"NRAS_Amp_369",
"NRAS_Amp_371",
"NRAS_Amp_374",
"NRAS_Amp_379"
],
"type": "set"
},
{
"metric": "Fraction of bases",
"value": 884111,
"type": "simple"
},
{
"metric": "Total_bases",
"value": 8062107,
"type": "simple"
}
],
"type": "set"
}
]
}
修改后的问题解决方法如下:
def parse:
[
inputs # read lines
| split(",") # split into columns
| select(length>0) # eliminate blanks
| .[:1] + [.[1:-3]] + .[-3:] # normalize columns
]
;
def simple(n;v): {metric:n, value:v|tonumber, type:"simple"};
def set(n;v): {metric:n, value:v, type:"set"};
def exons(v): [ v[] | split(";") | .[0], {"chromosome":.[1], "start":.[2], "end":.[3]} ];
def region:
set(.[0]; [
set("Exons"; exons(.[1])),
simple("Fraction of bases"; .[2]),
simple("Total_bases"; .[3])
]
)
;
{ "Exome regions": parse | map(region) }
我有一个 CSV 文件,我想使用 jq 解析并获得嵌套 JSON。我最近开始使用 JQ,我非常喜欢这个工具。我了解基本功能,但解析 csv 文件似乎有点困难,尤其是打印嵌套 objects.
示例输入
基因、外显子、总计、外显子碱基数、总碱基数、外显子碱基分数 PIK3CA,PIK3CA_Exon10;chr1;1000;1500,PIK3CA_Exon13;chr1;1000;1500,PIK3CA_Exon14;chr1;1000;1500,1927879,12993042,0.15 NRAS,NRAS_Exon4;chr1;1000;1500,NRAS_Amp_369;chr1;1000;1500,NRAS_Amp_371;chr1;1000;1500,NRAS_Amp_374;chr1;1000;1500, NRAS_Amp_379;chr1;1000;1500,884111,8062107,0.11
Header 和输入数据解释
第一列始终有一个值。第二列可以有多个外显子(1 个或多个)。您可以看到它在第 2 行有 3 个值,在第 3 行有 5 个值。外显子碱基将始终是倒数第二列,总碱基将是最后一列,外显子碱基分数将是最后一列。
备注
我添加的header是为了解释,可以删除或修改以进行处理
预期输出
{
"Exome regions":[
{
"metric":"PIK3CA",
"value":[
{
"metric":"Exons",
"value":[
"PIK3CA_Exon10",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"PIK3CA_Exon13",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"PIK3CA_Exon14",
{
"chromosome":"chr1",
"start":1000,
"end":1500
}
],
"type":"set"
},
{
"metric":"Fraction of bases",
"value":0.15,
"type":"simple"
},
{
"metric":"Total_bases",
"value":1927879,
"type":"simple"
}
],
"type":"set"
},
{
"metric":"NRAS",
"value":[
{
"metric":"Exons",
"value":[
"NRAS_Exon4",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"NRAS_Amp_369",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"NRAS_Amp_371",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"NRAS_Amp_374",
{
"chromosome":"chr1",
"start":1000,
"end":1500
},
"NRAS_Amp_379",
{
"chromosome":"chr1",
"start":1000,
"end":1500
}
],
"type":"set"
},
{
"metric":"Fraction of bases",
"value":0.11,
"type":"simple"
},
{
"metric":"Total_bases",
"value":884111,
"type":"simple"
}
],
"type":"set"
}
]
}
提前感谢您的帮助!!
PS:- 我需要添加更多信息,我必须编辑外显子字段并向每个外显子添加 "Chromosomes"、"Start" 和 "End"。在这里我给出了相同的开始和结束,但在实际情况下它因每个外显子而异。你能帮我解决这个问题吗? 此外,这些外显子的输入可以用任何其他字符分隔 too.Right 现在我用“;”分隔它
这是一个解决方案,(a) 根据关于 header 的评论(但见下文)假设没有 header 行; (b) 不 "slurp" 文件(即
不会将整个文件读入内存); (c) 假定 jq 的版本为 inputs
。 (如果你的jq没有inputs
,下面相应修改就很容易了。)
def parse_row:
split(",")
| length as $length
| .[1: $length - 3] as $exons
| { metric : .[0],
value: [ { metric: "Exons",
value: $exons,
type: "set" },
{ metric: "Fraction of bases",
value: (.[$length - 1] | tonumber),
type: "simple"
},
{ metric: "Total_bases",
value: (.[$length - 3] | tonumber),
type: "simple"
}
],
type: "set"
} ;
[inputs | parse_row]
| { "Exome regions": .}
jq 的适当调用应遵循以下几行:
jq -n -R -f program.jq input.txt
这将生成所需的 JSON。
(-R 代表 "raw input"。)
如果输入文件确实有 header 行,只要您删除“-n”command-line 选项,上述解决方案仍然有效。
请注意,虽然输入文件有 comma-separated 个值,但它并不是真正的 CSV 文件。
这是一个使用函数来解析和组装输出的解决方案:
def parse:
[
inputs # read lines
| split(",") # split into columns
| select(length>0) # eliminate blanks
| .[:1] + [.[1:-3]] + .[-3:] # normalize columns
]
;
def simple(n;v): {metric:n, value:v|tonumber, type:"simple"};
def set(n;v): {metric:n, value:v, type:"set"};
def region:
set(.[0]; [
set("Exons"; .[1]),
simple("Fraction of bases"; .[2]),
simple("Total_bases"; .[3])
]
)
;
{
"Exome regions": parse | map(region)
}
示例 运行(假设过滤器在 filter.jq
中,数据在 data.json
中)
$ jq -M -Rnr -f filter.jq data.json
{
"Exome regions": [
{
"metric": "PIK3CA",
"value": [
{
"metric": "Exons",
"value": [
"PIK3CA_Exon10",
"PIK3CA_Exon13",
"PIK3CA_Exon14"
],
"type": "set"
},
{
"metric": "Fraction of bases",
"value": 1927879,
"type": "simple"
},
{
"metric": "Total_bases",
"value": 12993042,
"type": "simple"
}
],
"type": "set"
},
{
"metric": "NRAS",
"value": [
{
"metric": "Exons",
"value": [
"NRAS_Exon4",
"NRAS_Amp_369",
"NRAS_Amp_371",
"NRAS_Amp_374",
"NRAS_Amp_379"
],
"type": "set"
},
{
"metric": "Fraction of bases",
"value": 884111,
"type": "simple"
},
{
"metric": "Total_bases",
"value": 8062107,
"type": "simple"
}
],
"type": "set"
}
]
}
修改后的问题解决方法如下:
def parse:
[
inputs # read lines
| split(",") # split into columns
| select(length>0) # eliminate blanks
| .[:1] + [.[1:-3]] + .[-3:] # normalize columns
]
;
def simple(n;v): {metric:n, value:v|tonumber, type:"simple"};
def set(n;v): {metric:n, value:v, type:"set"};
def exons(v): [ v[] | split(";") | .[0], {"chromosome":.[1], "start":.[2], "end":.[3]} ];
def region:
set(.[0]; [
set("Exons"; exons(.[1])),
simple("Fraction of bases"; .[2]),
simple("Total_bases"; .[3])
]
)
;
{ "Exome regions": parse | map(region) }