我试图解析从curl请求返回的JSON,就像这样:

curl 'http://twitter.com/users/username.json' |
    sed -e 's/[{}]/''/g' | 
    awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'

上面将JSON划分为多个字段,例如:

% ...
"geo_enabled":false
"friends_count":245
"profile_text_color":"000000"
"status":"in_reply_to_screen_name":null
"source":"web"
"truncated":false
"text":"My status"
"favorited":false
% ...

我如何打印一个特定的字段(由-v k=文本表示)?


当前回答

我用它从ffprobe JSON输出中提取视频时长:

MOVIE_INFO=`ffprobe "path/to/movie.mp4"  -show_streams -show_format -print_format json -v quiet`
MOVIE_SECONDS=`echo "$MOVIE_INFO"|grep -w \"duration\" |tail -1 | cut -d\" -f4 |cut -d \. -f 1`

它可以用来从任何JSON文件中提取值:

value=`echo "$jsondata" | grep -w \"key_name\" |tail -1 | cut -d\" -f4

其他回答

你可以使用jshon:

curl 'http://twitter.com/users/username.json' | jshon -e text

既然PowerShell是跨平台的,我想我就把它扔到那里,因为我发现它相当直观和非常简单。

curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json

ConvertFrom-Json将JSON转换为PowerShell自定义对象,这样您就可以轻松地使用这些属性。例如,如果你只想要'id'属性,你只需要这样做:

curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json | select -ExpandProperty id

如果你想从Bash内部调用整个东西,那么你必须像这样调用它:

powershell 'curl -s "https://api.github.com/users/lambda" | ConvertFrom-Json'

当然,有一个纯粹的PowerShell方法来做它没有卷曲,这将是:

Invoke-WebRequest 'https://api.github.com/users/lambda' | select -ExpandProperty Content | ConvertFrom-Json

最后,还有ConvertTo-Json,它可以很容易地将自定义对象转换为JSON。这里有一个例子:

(New-Object PsObject -Property @{ Name = "Tester"; SomeList = @('one','two','three')}) | ConvertTo-Json

它会生成这样的JSON:

{
"Name":  "Tester",
"SomeList":  [
                 "one",
                 "two",
                 "three"
             ]

}

诚然,在Unix上使用Windows shell有点亵渎神明,但PowerShell确实擅长某些事情,解析JSON和XML就是其中之一。这是跨平台版本PowerShell的GitHub页面

下面是shell书呆子使用POSIX shell(带local)和egrep的答案:JSON.sh, 4.7 KB。

这个东西有很多测试用例,所以它应该是正确的。它也是可管道的。它用于Bash的包管理器bpkg。

如果有人只想从简单的JSON对象中提取值,而不需要嵌套结构,那么甚至不需要离开Bash就可以使用正则表达式。

下面是我使用基于JSON标准的bash正则表达式定义的函数:

function json_extract() {
  local key=$1
  local json=$2

  local string_regex='"([^"\]|\\.)*"'
  local number_regex='-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?'
  local value_regex="${string_regex}|${number_regex}|true|false|null"
  local pair_regex="\"${key}\"[[:space:]]*:[[:space:]]*(${value_regex})"

  if [[ ${json} =~ ${pair_regex} ]]; then
    echo $(sed 's/^"\|"$//g' <<< "${BASH_REMATCH[1]}")
  else
    return 1
  fi
}

注意:对象和数组不支持作为值,但支持标准中定义的所有其他值类型。另外,只要具有完全相同的键名,无论对在JSON文档中有多深,都将匹配。

以OP为例:

$ json_extract text "$(curl 'http://twitter.com/users/username.json')"
My status

$ json_extract friends_count "$(curl 'http://twitter.com/users/username.json')"
245

你可以下载jq二进制文件到你的平台,然后运行(chmod +x jq):

$ curl 'https://twitter.com/users/username.json' | ./jq -r '.name'

它从json对象中提取“name”属性。

jq主页说它类似于JSON数据的sed。