将 JSON 解析为 shell 脚本中的数组 [英] Parse JSON to array in a shell script
问题描述
我正在尝试将 shell 脚本中的 JSON 对象解析为数组.
I'm trying to parse a JSON object within a shell script into an array.
例如:[Amanda, 25, http://mywebsite.com]
e.g.: [Amanda, 25, http://mywebsite.com]
JSON 看起来像:
{
"name" : "Amanda",
"age" : "25",
"websiteurl" : "http://mywebsite.com"
}
我不想使用任何库,最好能使用正则表达式或 grep.我已经完成了:
I do not want to use any libraries, it would be best if I could use a regular expression or grep. I have done:
myfile.json | grep name
这给了我名字":阿曼达".我可以为文件中的每一行循环执行此操作,并将其添加到数组中,但我只需要右侧而不是整行.
This gives me "name" : "Amanda". I could do this in a loop for each line in the file, and add it to an array but I only need the right side and not the entire line.
推荐答案
如果你真的不能使用合适的 JSON 解析器,比如 jq
[1],尝试基于 awk
的解决方案:
If you really cannot use a proper JSON parser such as jq
[1]
, try an awk
-based solution:
Bash 4.x:
readarray -t values < <(awk -F" 'NF>=3 {print $4}' myfile.json)
Bash 3.x:
IFS=$'
' read -d '' -ra values < <(awk -F" 'NF>=3 {print $4}' myfile.json)
这将所有属性 values 存储在 Bash 数组 ${values[@]}
中,您可以使用它声明 -p 值
.
This stores all property values in Bash array ${values[@]}
, which you can inspect with
declare -p values
.
这些解决方案有局限性:
These solutions have limitations:
- 每个属性都必须单独一行,
- 所有值都必须用双引号括起来,
- 不支持嵌入的转义双引号.
所有这些限制都强化了使用适当 JSON 解析器的建议.
All these limitations reinforce the recommendation to use a proper JSON parser.
注意:以下替代解决方案使用 Bash 4.x+ readarray -t values
命令,但它们也适用于 Bash 3.x 替代方案,IFS=$'
' read -d '' -ra values
.
Note: The following alternative solutions use the Bash 4.x+ readarray -t values
command, but they also work with the Bash 3.x alternative, IFS=$'
' read -d '' -ra values
.
grep
+ cut
组合:单个 grep
命令不起作用(除非您使用 GNU grep
- 见下文),但添加 cut
有帮助:
grep
+ cut
combination: A single grep
command won't do (unless you use GNU grep
- see below), but adding cut
helps:
readarray -t values < <(grep '"' myfile.json | cut -d '"' -f4)
<小时>
GNU grep
:使用-P
来支持PCREs,支持K
删除到目前为止匹配的所有内容(后视断言的更灵活替代方案)以及前瞻断言((?=...)
):
GNU grep
: Using -P
to support PCREs, which support K
to drop everything matched so far (a more flexible alternative to a look-behind assertion) as well as look-ahead assertions ((?=...)
):
readarray -t values < <(grep -Po ':s*"K.+(?="s*,?s*$)' myfile.json)
<小时>
最后,这是一个纯 Bash (3.x+) 解决方案:
在性能方面使其成为可行的替代方案的原因是在每次循环迭代中不调用任何外部实用程序;但是,对于较大的输入文件,基于外部实用程序的解决方案会更快.
What makes this a viable alternative in terms of performance is that no external utilities are called in each loop iteration; however, for larger input files, a solution based on external utilities will be much faster.
#!/usr/bin/env bash
declare -a values # declare the array
# Read each line and use regex parsing (with Bash's `=~` operator)
# to extract the value.
while read -r line; do
# Extract the value from between the double quotes
# and add it to the array.
[[ $line =~ :[[:blank:]]+"(.*)" ]] && values+=( "${BASH_REMATCH[1]}" )
done < myfile.json
declare -p values # print the array
<小时>
[1] 以下是基于jq
的强大解决方案的样子(Bash 4.x):readarray -t values <<(jq -r '.[]' myfile.json)
[1] Here's what a robust jq
-based solution would look like (Bash 4.x):
readarray -t values < <(jq -r '.[]' myfile.json)
这篇关于将 JSON 解析为 shell 脚本中的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!