0

I have a text file containing a very long line of JSON data and I need to extract the value of some field.  I realize the easiest way to do this would be to use jq or grep -o; however, I am on a company machine, so I cannot install jq, and we are using a version of Solaris where grep does not have the -o option. Currently I am using the command:

cat json.file   |
    tr "," "\n" |
    awk '/customfield_10701/ { print $0 }' |
    tr '"' "\n" |
    awk 'NR==4'

The above works fine, but I can't help but feel that it is overly complicated and there should be a more elegant solution.

Example of json.file:

... jshdgfjhsdgfjh,"customfield_10701":"Some Branch","customfield_10702ksghdkfsdkfjkj ...

With my current command I get:

Some Branch

(which is what I want).

4
  • You got what you want, so why did you raise the question?
    – cuonglm
    Jun 13 '16 at 15:53
  • 1
    Because I can't help but think that my approach will have a significantly longer run time then if there is a single command that can accomplish this. So I'm trying to find out if anyone knows of a simplified version of my solution or if I'm being redundant in my command.
    – Void
    Jun 13 '16 at 16:02
  • 1
    If you must use bash, lose the cat for starts? Parsing JSON with bash tools may not always work the same way every time. You may want to consider using languages that can parse JSON or jsawk: github.com/micha/jsawk
    – KM.
    Jun 13 '16 at 16:13
  • 100% cut, verrrry fragile: cut -d'"' -f 4 input.json
    – agc
    Jun 13 '16 at 16:50
3

If you are sure there are no " characters in the data you're looking for and if there's only one line containing a "customfield_10701" entry in the file, then

sed -n 's/.*"customfield_10701":"\([^"]*\)".*/\1/p'

e.g.,

$ cat x
... jshdgfjhsdgfjh,"customfield_10701":"Some Branch","customfield_10702ksghdkfsdkfjkj ...
$ sed -n 's/.*"customfield_10701":"\([^"]*\)".*/\1/p' x
Some Branch
4
  • Of course this also assumes that there is no field with a value of "customfield_10701". Jun 13 '16 at 17:12
  • @G-Man it shouldn't because a value would be followed by a , whereas this regex uses a : as the field:value separator. Jun 13 '16 at 17:14
  • Oh, good point; I typed before I thought. Jun 13 '16 at 17:18
  • Thanks Stephen! I am receiving JSON as a response from a server, which gives the data with no newline character at the end so this solution doesn't work properly as is, but there is an easy solution. So for anyone who is in a similar situation you can pipe the data through '{ cat ; echo ; }' before piping through 'sed' which will append a newline character to the data and everything should work properly.
    – Void
    Jun 13 '16 at 21:32
0

You don't need to use tr to transform commas into newlines. And then back again. You can tell awk to use a comma as the Input Record Separator (RS).

awk -F':' -v RS=',' '/customfield_10701/ { gsub(/"/,"",$2); print $2 }' json.file

gsub() is used to remove the double-quotes " (if any) from field 2.

If required, you can also use gsub() to remove leading and trailing spaces and tabs, too:

awk -F':' -v RS=',' '/customfield_10701/ {
    gsub(/"|^[[:blank:]]+|[[:blank:]]+$/,"",$2);
    print $2
}' json.file

Note that the Output Record Separator (ORS) is not automatically changed when RS is changed, it stays at the default (a newline) unless you set it (e.g. with -v ORS=',').

0

The following test works for me using bash 3 builtin regex engine and does not require external programs:

json='"jshdgfjhsdgfjh,"customfield_10701":"Some Branch","customfield_10702ksghdkfsdkfjkj"'

regex_hint=customfield_10701

[[ $json =~ $regex_hint\":\"(.+)\", ]] && printf '%s\n' "${BASH_REMATCH[1]}" 

Prints: Some Branch

The regex between '( )' is the "capture group 1", which is saved in "${BASH_REMATCH1}"

Note the bash builtin supports POSIX Extended Regular Expressions instead of the more well known Perl Compatible Regular Expressions

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.