有很多类似的问题,但没有一个问题可以动态加入2个文件。 我想做的是动态编辑以下结构:
{
"features": [
{
"type": "Feature",
"properties": {
"name": "0",
"height": 0.7
}
},
{
"type": "Feature",
"properties": {
"name": "1",
"height": 0
}
}
]
}
我只想用另一个txt文件中1d数组中的随机值替换一个字段.features[].properties.name
。我已经准备了8,000个功能和大约100个名称。
这是我现在因错误而失败的原因:
#!/bin/bash
declare -a names=("name1" "name2" "name3")
jq '{
"features" : [
"type" : "Feature",
"properties" : {
"name" : `$names[seq 0 100]`,
"height" : .features[].properties.height
},
.features[].geometry
]
}' < areas.json
是否甚至可以在单个命令中执行操作,还是应该使用python或js执行此类任务?
答案 0 :(得分:2)
您的文档(https://echarts.baidu.com/examples/data-gl/asset/data/buildings.json)实际上足够小,因此我们无需执行任何疯狂的内存保存技巧即可使其工作;原有功能如下:
# create sample data
[[ -e words.txt ]] || printf '%s\n' 'First Word' 'Second Word' 'Third Word' >words.txt
# actually run the replacements
jq -n --slurpfile buildings buildings.json '
# define a jq function that changes the current property name with the next input
def replaceName: (.properties.name |= input);
# now, for each document in buildings.json, replace each name it contains
$buildings[] | (.features |= map(replaceName))
' < <(shuf -r words.txt | jq -R .)
之所以行之有效,是因为shuf -r words.txt
创建了一个从words.txt
中随机选择的无休止的单词流,并且流程替换中的jq -R .
用字符串作为引号。 (因为我们只对input
中的每个项目调用buildings.json
,所以在该文件的内容完全耗尽后,我们不会尝试继续运行。)
对于问题中给出的两记录小文档,输出如下:
{
"features": [
{
"type": "Feature",
"properties": {
"name": "Third Word",
"height": 0.7
}
},
{
"type": "Feature",
"properties": {
"name": "Second Word",
"height": 0
}
}
]
}
...实际词每次运行都会有所不同;完整的外部托管文件也经过了烟雾测试。
答案 1 :(得分:2)
这是解决问题的一种方法,它使用用jq编写的非常简单的PRNG来随机选择名称进行替换 复制自https://rosettacode.org/wiki/Random_numbers#jq
jq --argjson names '["name1","name2","name3","name4"]' \
-f areas.jq areas.json
# The random numbers are in [0 -- 32767] inclusive.
# Input: an array of length at least 2 interpreted as [count, state, ...]
# Output: [count+1, newstate, r] where r is the next pseudo-random number.
def next_rand_Microsoft:
.[0] as $count | .[1] as $state
| ( (214013 * $state) + 2531011) % 2147483648 # mod 2^31
| [$count+1 , ., (. / 65536 | floor) ] ;
# generate a stream of random integers < $n
def randoms($n):
def r: next_rand_Microsoft
| (.[2] % $n), r;
[0,11] | r ;
. as $in
| ($names|length) as $count
| (.features|length) as $n
| [limit($n; randoms($count))] as $randoms
| reduce range(0; $n) as $i (.;
.features[$i].properties.name = $names[$randoms[$i]] )
答案 2 :(得分:1)
假设您的area.json是有效的JSON,那么我相信以下内容将接近完成您的预期编辑:
names='["name1","name2","name3","name4"]'
jq --argjson names "$names" '.features[].properties.name = $names
' < areas.json
但是,考虑到您提出的解决方案,对于我来说,“一维数组的随机值”的含义还不清楚。如果您是说应该随机选择索引(如PRNG),那么我建议使用您喜欢的PRNG计算该索引,并将该随机值作为jq的另一个参数传递,如以下部分所示。
所以问题就变成了如何转换文本
['name1','name2','name3','name4']
转换为有效的JSON数组。无论是否使用jq,都有许多方法可以完成,但是我认为最好还是将其作为单独的问题还是作为练习,因为方法的选择可能取决于具体的细节,而在本问中未提及。就个人而言,我会尽可能使用sed
;您也可以考虑使用hjson,如以下部分所述。
hjson -j <<< "['name1','name2','name3','name4']" > names.json.tmp
function randint {
awk -v n="$(jq length names.json.tmp)" '
function randint(n) {return int(n * rand())}
BEGIN {srand(); print randint(n)}'
}
jq --argfile names names.json.tmp --argjson n $(randint) '
.features[].properties.name = $names[$n]
' < areas.json
当前,jq没有内置的PRNG,但是如果您想使用jq,并且希望为每次出现的.name字段从“名称”数组中随机选择一个值(使用替换?), ,那么一种选择是使用您喜欢的PRNG预先计算一个随机选择的名称数组(长度为features | length
的数组),然后将该数组传递给jq:
jq --argjson randomnames "$randomnames" '
reduce range(0; .features[]|length) as $i (.;
.features[$i].properties.name = $randomnames[$i])
' < areas.json
另一种选择是使用用jq编写的PRNG,如本页其他位置所示。