unc*_*der 11 bash shell parsing json
我正在尝试将shell脚本中的JSON对象解析为数组.
例如:[阿曼达,25岁,http://mywebsite.com]
JSON看起来像:
{
"name" : "Amanda",
"age" : "25",
"websiteurl" : "http://mywebsite.com"
}
Run Code Online (Sandbox Code Playgroud)
我不想使用任何库,如果我可以使用正则表达式或grep最好.我已经做好了:
myfile.json | grep name
Run Code Online (Sandbox Code Playgroud)
这给了我"名字":"阿曼达".我可以在循环中为文件中的每一行执行此操作,并将其添加到数组中,但我只需要右侧而不是整行.
mkl*_*nt0 16
如果你真的不能使用适当的JSON解析器,如[1]
,请尝试基于解决方案:jqawk
Bash 4.x:
readarray -t values < <(awk -F\" 'NF>=3 {print $4}' myfile.json)
Run Code Online (Sandbox Code Playgroud)
Bash 3.x:
IFS=$'\n' read -d '' -ra values < <(awk -F\" 'NF>=3 {print $4}' myfile.json)
Run Code Online (Sandbox Code Playgroud)
这会将所有属性值存储在Bash数组中${values[@]},您可以使用它来检查
declare -p values.
这些解决方案有局限性
所有这些限制都强化了使用适当的JSON解析器的建议.
注意:以下替代解决方案使用Bash 4.x + readarray -t values命令,但它们也适用于Bash 3.x替代方案IFS=$'\n' read -d '' -ra values.
grep+ cut组合:单个grep命令不会(除非你使用GNU grep - 见下文),但添加cut帮助:
readarray -t values < <(grep '"' myfile.json | cut -d '"' -f4)
Run Code Online (Sandbox Code Playgroud)
GNU grep:-P用于支持PCRE,它支持\K删除到目前为止匹配的所有内容(一种更灵活的替代后面的断言)以及前瞻断言((?=...)):
readarray -t values < <(grep -Po ':\s*"\K.+(?="\s*,?\s*$)' myfile.json)
Run Code Online (Sandbox Code Playgroud)
最后,这是一个纯粹的Bash(3.x +)解决方案:
使其在性能方面成为可行的替代方案的原因是在每次循环迭代中都不会调用外部实用程序 ; 但是,对于较大的输入文件,基于外部实用程序的解决方案将更快.
#!/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
Run Code Online (Sandbox Code Playgroud)
[1]这是基于强大jq的解决方案的样子(Bash 4.x):
readarray -t values < <(jq -r '.[]' myfile.json)
jq 足以解决这个问题
paste -s <(jq '.files[].name' YourJsonString) <(jq '.files[].age' YourJsonString) <( jq '.files[].websiteurl' YourJsonString)
Run Code Online (Sandbox Code Playgroud)
这样你就可以得到一个表格,你可以 grep 任何行或 awk 打印你想要的任何列