之前曾有人问过这个问题,但我发现我的sed/grep/awk技能太基本了,无法从这些技能转向定制解决方案,因为我几乎从未使用过shell脚本。
我有一个很大的文本文件(超过10万行),其中每行定义一个GeoJSON对象,每个这样的对象都包含一个称为“县”的属性(总共有100个不同的县)。这是一个片段:
{"type": "Feature", "properties": {"county":"ALAMANCE", "vBLA": 0, "vWHI": 4, "vDEM": 0, "vREP": 2, "vUNA": 2, "vTOT": 4}, "geometry": {"type":"Polygon","coordinates":[[[-79.537429,35.843303],[-79.542428,35.843303],[-79.542428,35.848302],[-79.537429,35.848302],[-79.537429,35.843303]]]}},
{"type": "Feature", "properties": {"county":"NEW HANOVER", "vBLA": 0, "vWHI": 0, "vDEM": 0, "vREP": 0, "vUNA": 0, "vTOT": 0}, "geometry": {"type":"Polygon","coordinates":[[[-79.532429,35.843303],[-79.537428,35.843303],[-79.537428,35.848302],[-79.532429,35.848302],[-79.532429,35.843303]]]}},
{"type": "Feature", "properties": {"county":"ALAMANCE", "vBLA": 0, "vWHI": 0, "vDEM": 0, "vREP": 0, "vUNA": 0, "vTOT": 0}, "geometry": {"type":"Polygon","coordinates":[[[-79.527429,35.843303],[-79.532428,35.843303],[-79.532428,35.848302],[-79.527429,35.848302],[-79.527429,35.843303]]]}},
我需要将其拆分为100个单独的文件,每个文件包含一个县的GeoJSON,每个文件名为xxxx_bins_2016.json(其中xxxx是县的名称)。我还希望每个此类文件末尾的最后一个字符(逗号)消失。
如果重要的话,我正在Mac OSX中进行此操作。我希望通过研究您可以提出的任何解决方案来学到很多东西,因此,如果您想花些时间解释“为什么”以及“什么”,那将是很棒的。谢谢!
编辑以明确有不同的县名,其中一些是两个单词的名字。
最佳答案
jq
可以做到这一点;它可以对输入和输出每组一行文本进行分组。然后,shell 负责将每一行写入适当命名的文件。 jq
本身并没有真正能够打开文件进行写入,这将允许您在单个进程中执行此操作。
jq -Rn -c '[inputs[:-1]|fromjson] | group_by(.properties.county)[]' tmp.json |
while IFS= read -r line; do
county=$(jq -r '.[0].properties.county' <<< $line)
jq -r '.[]' <<< "$line" > "$county.txt"
done
[inputs[:-1]|fromjson]
将文件的每一行作为一个字符串读取,去掉结尾的逗号,然后将该行解析为 JSON 并将这些行包装成一个数组。结果数组按县名排序和分组,然后写入标准输出,每行一组。Shell循环读取每一行,并通过调用
jq
从组的第一个元素中提取县名,然后再次使用jq
将组的每个元素写入相应的文件,每行又一个元素。(快速浏览 https://github.com/stedolan/jq/issues 似乎还没有显示对
output
函数的任何请求,该函数可以让您从 jq
过滤器内部打开和写入文件。我在想类似的东西jq -Rn '... | group_by(.properties.county) | output("\(.properties.county).txt")' tmp.json
不需要 shell 循环。)
关于Bash/*NIX : split a file into multiple files on a substring,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42444820/