json.sh 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. # https://github.com/dominictarr/JSON.sh
  2. # Code is licensed under the MIT license
  3. # Copyright (c) 2011 Dominic Tarr
  4. throw () {
  5. echo "$*" >&2
  6. exit 1
  7. }
  8. tokenize () {
  9. local ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
  10. local CHAR='[^[:cntrl:]"\\]'
  11. local STRING="\"$CHAR*($ESCAPE$CHAR*)*\""
  12. local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?'
  13. local KEYWORD='null|false|true'
  14. local SPACE='[[:space:]]+'
  15. egrep -ao "$STRING|$NUMBER|$KEYWORD|$SPACE|." --color=never |
  16. egrep -v "^$SPACE$" # eat whitespace
  17. }
  18. parse_array () {
  19. local index=0
  20. local ary=''
  21. read -r token
  22. case "$token" in
  23. ']') ;;
  24. *)
  25. while :
  26. do
  27. parse_value "$1" "$index"
  28. let index=$index+1
  29. ary="$ary""$value"
  30. read -r token
  31. case "$token" in
  32. ']') break ;;
  33. ',') ary="$ary," ;;
  34. *) throw "EXPECTED , or ] GOT ${token:-EOF}" ;;
  35. esac
  36. read -r token
  37. done
  38. ;;
  39. esac
  40. value=`printf '[%s]' $ary`
  41. }
  42. parse_object () {
  43. local key
  44. local obj=''
  45. read -r token
  46. case "$token" in
  47. '}') ;;
  48. *)
  49. while :
  50. do
  51. case "$token" in
  52. '"'*'"') key=$token ;;
  53. *) throw "EXPECTED string GOT ${token:-EOF}" ;;
  54. esac
  55. read -r token
  56. case "$token" in
  57. ':') ;;
  58. *) throw "EXPECTED : GOT ${token:-EOF}" ;;
  59. esac
  60. read -r token
  61. parse_value "$1" "$key"
  62. obj="$obj$key:$value"
  63. read -r token
  64. case "$token" in
  65. '}') break ;;
  66. ',') obj="$obj," ;;
  67. *) throw "EXPECTED , or } GOT ${token:-EOF}" ;;
  68. esac
  69. read -r token
  70. done
  71. ;;
  72. esac
  73. value=`printf '{%s}' "$obj"`
  74. }
  75. parse_value () {
  76. local jpath="${1:+$1,}$2"
  77. case "$token" in
  78. '{') parse_object "$jpath" ;;
  79. '[') parse_array "$jpath" ;;
  80. # At this point, the only valid single-character tokens are digits.
  81. ''|[^0-9]) throw "EXPECTED value GOT ${token:-EOF}" ;;
  82. *) value=$token ;;
  83. esac
  84. printf "[%s]\t%s\n" "$jpath" "$value"
  85. }
  86. parse () {
  87. read -r token
  88. parse_value
  89. read -r token
  90. case "$token" in
  91. '') ;;
  92. *) throw "EXPECTED EOF GOT $token" ;;
  93. esac
  94. }
  95. if [ $0 = $BASH_SOURCE ];
  96. then
  97. tokenize | parse
  98. fi