阅读shell脚本中的JSON数据

在shell中,我有一个要求,我必须阅读以下格式的JSON响应:

{ "Messages": [ { "Body": "172.16.1.42|/home/480/1234/5-12-2013/1234.toSort", "ReceiptHandle": "uUk89DYFzt1VAHtMW2iz0VSiDcGHY+H6WtTgcTSgBiFbpFUg5lythf+wQdWluzCoBziie8BiS2GFQVoRjQQfOx3R5jUASxDz7SmoCI5bNPJkWqU8ola+OYBIYNuCP1fYweKl1BOFUF+o2g7xLSIEkrdvLDAhYvHzfPb4QNgOSuN1JGG1GcZehvW3Q/9jq3vjYVIFz3Ho7blCUuWYhGFrpsBn5HWoRYE5VF5Bxc/zO6dPT0n4wRAd3hUEqF3WWeTMlWyTJp1KoMyX7Z8IXH4hKURGjdBQ0PwlSDF2cBYkBUA=", "MD5OfBody": "53e90dc3fa8afa3452c671080569642e", "MessageId": "e93e9238-f9f8-4bf4-bf5b-9a0cae8a0ebc" } ] } 

在这里,我只关心“身体”的财产价值。 我做了一些不成功的尝试,如:

  jsawk -a 'return this.Body' 

要么

  awk -vk="Body" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]} 

但是这还不够。 谁能帮我这个?

jq在命令行上parsingjson:

  jq '.Body' 

访问jq: https ://stedolan.github.io/jq/

TL;博士

 $ cat /tmp/so.json | underscore select '.Messages .Body' ["172.16.1.42|/home/480/1234/5-12-2013/1234.toSort"] 

Javascript CLI工具

您可以使用Javascript CLI工具

  • 下划线 :
  • json:select() :用于JSON的类CSSselect器。

select一个addons所有name孩子:

 underscore select ".addons > .name" 

underscore-cli提供了其他真实世界的例子以及json:select()doc 。

同样使用Bash正则expression式。 应该能够抢夺任何键/值对。

 key="Body" re="\"($key)\": \"([^\"]*)\"" while read -rl; do if [[ $l =~ $re ]]; then name="${BASH_REMATCH[1]}" value="${BASH_REMATCH[2]}" echo "$name=$value" else echo "No match" fi done 

正则expression式可以调整为匹配多个空格/制表符或换行符。 如果价值已经embedded,这将是不行的"这是一个例子,最好使用一些”工业“parsing器:)

这是一个简单的方法:将JSON转换成bashvariables来eval它们。

这只适用于:

  • 不包含嵌套数组的JSON,和
  • JSON来自可靠的来源(否则它可能会混淆你的shell脚本,也许它甚至可能会损害你的系统, 你已经被警告过了

那么,是的,它使用PERL来完成这项工作,这要归功于CPAN,但是它足够小,可以直接包含在脚本中,因此debugging起来很快,很容易:

 json2bash() { perl -MJSON -0777 -n -E 'sub J { my ($p,$v) = @_; my $r = ref $v; if ($r eq "HASH") { J("${p}_$_", $v->{$_}) for keys %$v; } elsif ($r eq "ARRAY") { $n = 0; J("$p"."[".$n++."]", $_) foreach @$v; } else { $v =~ '"s/'/'\\\\''/g"'; $p =~ s/^([^[]*)\[([0-9]*)\](.+)$/$1$3\[$2\]/; $p =~ tr/-/_/; $p =~ tr/A-Za-z0-9_[]//cd; say "$p='\''$v'\'';"; } }; J("json", decode_json($_));' } 

使用它像eval "$(json2bash <<<'{"a":["b","c"]}')"

虽然没有经过严格testing。 更新,警告和更多的例子见我的GIST 。